home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1995 #5 & #6 / Amiga Plus CD - 1995 - No. 5 and 6.iso / pd / netz / term / extras / source / term-source.lha / termConsole.c < prev    next >
C/C++ Source or Header  |  1995-07-04  |  57KB  |  3,475 lines

  1. /*
  2. **    termConsole.c
  3. **
  4. **    High-level terminal console routines
  5. **
  6. **    Copyright © 1990-1995 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "termGlobal.h"
  11.  
  12.     /* Character set modes. */
  13.  
  14. enum    {    MODE_STANDARD,MODE_GFX };
  15.  
  16.     /* Hints for the data flow scanner. */
  17.  
  18. STATIC WORD        ScanStart,
  19.             ScanEnd;
  20.  
  21. STATIC WORD __far    AttentionCount[SCAN_COUNT],
  22.             AttentionLength[SCAN_COUNT],
  23.             FlowCount;
  24.  
  25.     /* Temporary console working buffer. */
  26.  
  27. STATIC UBYTE __far    ConTempBuffer[512];
  28.  
  29.     /* ConTranslateSetup():
  30.      *
  31.      *    Set up for buffer translation.
  32.      */
  33.  
  34. STATIC VOID __inline
  35. ConTranslateSetup(struct TranslationHandle *Handle,STRPTR SourceBuffer,LONG SourceLen,STRPTR DestinationBuffer,LONG DestinationLen,struct TranslationEntry **Table)
  36. {
  37.     Handle -> LocalBuffer        = NULL;
  38.     Handle -> LocalLen        = 0;
  39.  
  40.     Handle -> SourceBuffer        = SourceBuffer;
  41.     Handle -> SourceLen        = SourceLen;
  42.  
  43.     Handle -> DestinationBuffer    = DestinationBuffer;
  44.     Handle -> DestinationLen    = DestinationLen;
  45.  
  46.     Handle -> Table            = Table;
  47. }
  48.  
  49.     /* ConTranslateBuffer(struct TranslationHandle *Handle):
  50.      *
  51.      *    Translate buffer contents according to
  52.      *    translation table contents.
  53.      */
  54.  
  55. STATIC LONG __inline
  56. ConTranslateBuffer(struct TranslationHandle *Handle)
  57. {
  58.     register STRPTR                 Data        = Handle -> DestinationBuffer;
  59.     register LONG                 BytesWritten    = 0;
  60.     register struct TranslationEntry    *Entry;
  61.  
  62.         /* Are we to return any translated data? */
  63.  
  64.     while(Handle -> LocalLen && BytesWritten < Handle -> DestinationLen)
  65.     {
  66.             /* Decrement number of bytes in buffer. */
  67.  
  68.         Handle -> LocalLen--;
  69.  
  70.             /* Return next character. */
  71.  
  72.         *Data++ = *Handle -> LocalBuffer++;
  73.  
  74.             /* Add another byte. */
  75.  
  76.         BytesWritten++;
  77.     }
  78.  
  79.         /* Loop until done. */
  80.  
  81.     while(Handle -> SourceLen && BytesWritten < Handle -> DestinationLen)
  82.     {
  83.             /* Another byte eaten. */
  84.  
  85.         Handle -> SourceLen--;
  86.  
  87.             /* Get table entry. */
  88.  
  89.         if(Entry = Handle -> Table[*Handle -> SourceBuffer++])
  90.         {
  91.                 /* Copy to local data area. */
  92.  
  93.             Handle -> LocalBuffer    = Entry -> String;
  94.             Handle -> LocalLen    = Entry -> Len;
  95.  
  96.                 /* Translate the data. */
  97.  
  98.             while(Handle -> LocalLen && BytesWritten < Handle -> DestinationLen)
  99.             {
  100.                     /* Decrement number of bytes in buffer. */
  101.  
  102.                 Handle -> LocalLen--;
  103.  
  104.                     /* Return next character. */
  105.  
  106.                 *Data++ = *Handle -> LocalBuffer++;
  107.  
  108.                     /* Add another byte. */
  109.  
  110.                 BytesWritten++;
  111.             }
  112.         }
  113.     }
  114.  
  115.     return(BytesWritten);
  116. }
  117.  
  118.     /* TrapFilter(register STRPTR Data,register LONG Size):
  119.      *
  120.      *    Handle the trap list, similar to FlowFilter().
  121.      */
  122.  
  123. STATIC VOID __regargs
  124. TrapFilter(register STRPTR Data,register LONG Size)
  125. {
  126.     STATIC LONG WaitCount = 0;
  127.  
  128.     struct List    *List = (struct List *)&GenericListTable[GLIST_TRAP] -> ListHeader;
  129.     struct TrapNode    *Node;
  130.  
  131.     register UBYTE c,Mask;
  132.  
  133.     ObtainSemaphore(&GenericListTable[GLIST_TRAP] -> ListSemaphore);
  134.  
  135.     if(Config -> SerialConfig -> StripBit8)
  136.         Mask = 0x7F;
  137.     else
  138.         Mask = 0xFF;
  139.  
  140.     do
  141.     {
  142.         register BOOLEAN MatchMade;
  143.  
  144.         c = (*Data++) & Mask;
  145.  
  146.         do
  147.         {
  148.             MatchMade = FALSE;
  149.  
  150.             for(Node = (struct TrapNode *)List -> lh_Head ; Node -> Node . ln_Succ ; Node = (struct TrapNode *)Node -> Node . ln_Succ)
  151.             {
  152.                 if(Node -> Count == WaitCount)
  153.                 {
  154.                     if(c == (Node -> Sequence[WaitCount] & Mask))
  155.                     {
  156.                         MatchMade = TRUE;
  157.  
  158.                         if(++Node -> Count == Node -> SequenceLen)
  159.                         {
  160.                             struct DataMsg *Msg;
  161.  
  162.                             Node -> Count = 0;
  163.  
  164.                             if(Msg = (struct DataMsg *)CreateMsgItem(sizeof(struct DataMsg) + strlen(Node -> Command) + 1))
  165.                             {
  166.                                 Msg -> Type = DATAMSGTYPE_SERIALCOMMAND;
  167.                                 Msg -> Data = (STRPTR)(Msg + 1);
  168.  
  169.                                 strcpy(Msg -> Data,Node -> Command);
  170.  
  171.                                 PutMsgItem(SpecialQueue,(struct MsgItem *)Msg);
  172.                             }
  173.                         }
  174.                     }
  175.                 }
  176.             }
  177.  
  178.             if(MatchMade)
  179.                 WaitCount++;
  180.             else
  181.             {
  182.                 if(WaitCount)
  183.                 {
  184.                     WaitCount = 0;
  185.  
  186.                     for(Node = (struct TrapNode *)List -> lh_Head ; Node -> Node . ln_Succ ; Node = (struct TrapNode *)Node -> Node . ln_Succ)
  187.                         Node -> Count = 0;
  188.                 }
  189.                 else
  190.                     break;
  191.             }
  192.         }
  193.         while(!WaitCount);
  194.     }
  195.     while(--Size);
  196.  
  197.     ReleaseSemaphore(&GenericListTable[GLIST_TRAP] -> ListSemaphore);
  198. }
  199.  
  200.     /* FlowFilter(register STRPTR Data,register LONG Size,UBYTE Mask):
  201.      *
  202.      *    Data flow filter.
  203.      */
  204.  
  205. STATIC VOID __regargs
  206. FlowFilter(register STRPTR Data,register LONG Size,register UBYTE Mask)
  207. {
  208.     register UBYTE c;
  209.  
  210.         /* Run until done. */
  211.  
  212.     do
  213.     {
  214.         if(c = (*Data++ & Mask))
  215.         {
  216.  
  217.                 /* We already got a `CONNECT',
  218.                  * Continue scanning the serial output
  219.                  * data for the actual baud rate.
  220.                  */
  221.  
  222.             if(BaudPending)
  223.             {
  224.                 if(c < ' ')
  225.                 {
  226.                     while(BaudCount > 0 && BaudBuffer[BaudCount - 1] == ' ')
  227.                         BaudCount--;
  228.  
  229.                     BaudBuffer[BaudCount] = 0;
  230.  
  231.                     FlowInfo . Connect = TRUE;
  232.                     FlowInfo . Changed = TRUE;
  233.  
  234.                     BaudPending = FALSE;
  235.  
  236.                     DTERate = GetBaudRate(BaudBuffer);
  237.  
  238.                     if(Quiet && Size > 1)
  239.                     {
  240.                         DataHold = Data;
  241.                         DataSize = Size - 1;
  242.                     }
  243.                 }
  244.                 else
  245.                 {
  246.                     if(BaudCount || c != ' ')
  247.                     {
  248.                         BaudBuffer[BaudCount++] = c;
  249.  
  250.                         if(BaudCount == 79)
  251.                         {
  252.                             while(BaudCount > 0 && BaudBuffer[BaudCount - 1] == ' ')
  253.                                 BaudCount--;
  254.  
  255.                             BaudBuffer[BaudCount] = 0;
  256.  
  257.                             FlowInfo . Connect = TRUE;
  258.                             FlowInfo . Changed = TRUE;
  259.  
  260.                             BaudPending = FALSE;
  261.  
  262.                             DTERate = GetBaudRate(BaudBuffer);
  263.  
  264.                             if(Quiet && Size > 1)
  265.                             {
  266.                                 DataHold = Data;
  267.                                 DataSize = Size - 1;
  268.                             }
  269.                         }
  270.                     }
  271.                 }
  272.             }
  273.             else
  274.             {
  275.                 register BYTE MatchMade;
  276.                 register WORD i;
  277.  
  278.                 do
  279.                 {
  280.                     MatchMade = FALSE;
  281.  
  282.                         /* Scan all ID strings for matches. */
  283.  
  284.                     for(i = ScanStart ; i <= ScanEnd ; i++)
  285.                     {
  286.                             /* This sequence is a likely
  287.                              * match.
  288.                              */
  289.  
  290.                         if(AttentionCount[i] == FlowCount)
  291.                         {
  292.                                 /* Does the character
  293.                                  * fit into the sequence?
  294.                                  */
  295.  
  296.                             if(c == AttentionBuffers[i][FlowCount] & Mask)
  297.                             {
  298.                                 MatchMade = TRUE;
  299.  
  300.                                     /* Did we hit the
  301.                                      * last character
  302.                                      * in the sequence?
  303.                                      */
  304.  
  305.                                 if(++AttentionCount[i] == AttentionLength[i])
  306.                                 {
  307.                                         /* We've got a valid
  308.                                          * sequence, now look
  309.                                          * which flags to change.
  310.                                          */
  311.  
  312.                                     switch(i)
  313.                                     {
  314.                                             /* We got a `no carrier' message. */
  315.  
  316.                                         case SCAN_NOCARRIER:
  317.  
  318.                                             if(!FlowInfo . NoCarrier)
  319.                                             {
  320.                                                 FlowInfo . NoCarrier    = TRUE;
  321.                                                 FlowInfo . Changed    = TRUE;
  322.                                             }
  323.  
  324.                                             break;
  325.  
  326.                                             /* Got another call. */
  327.  
  328.                                         case SCAN_RING:
  329.  
  330.                                             if(!FlowInfo . Ring)
  331.                                             {
  332.                                                 FlowInfo . Ring        = TRUE;
  333.                                                 FlowInfo . Changed    = TRUE;
  334.                                             }
  335.  
  336.                                             break;
  337.  
  338.                                             /* Got a voice call. */
  339.  
  340.                                         case SCAN_VOICE:
  341.  
  342.                                             if(!FlowInfo . Voice)
  343.                                             {
  344.                                                 FlowInfo . Voice    = TRUE;
  345.                                                 FlowInfo . Changed    = TRUE;
  346.                                             }
  347.  
  348.                                             break;
  349.  
  350.                                             /* Modem reported an error. */
  351.  
  352.                                         case SCAN_ERROR:
  353.  
  354.                                             if(!FlowInfo . Error)
  355.                                             {
  356.                                                 FlowInfo . Error    = TRUE;
  357.                                                 FlowInfo . Changed    = TRUE;
  358.                                             }
  359.  
  360.                                             break;
  361.  
  362.                                             /* Got a connect message. */
  363.  
  364.                                         case SCAN_CONNECT:
  365.  
  366.                                             ObtainSemaphore(&OnlineSemaphore);
  367.  
  368.                                             if(!Online)
  369.                                             {
  370.                                                 BaudBuffer[0]    = 0;
  371.  
  372.                                                 BaudPending    = TRUE;
  373.                                                 BaudCount    = 0;
  374.                                             }
  375.  
  376.                                             ReleaseSemaphore(&OnlineSemaphore);
  377.  
  378.                                             break;
  379.  
  380.                                             /* Line is busy. */
  381.  
  382.                                         case SCAN_BUSY:
  383.  
  384.                                             if(!FlowInfo . Busy)
  385.                                             {
  386.                                                 FlowInfo . Busy        = TRUE;
  387.                                                 FlowInfo . Changed    = TRUE;
  388.                                             }
  389.  
  390.                                             break;
  391.  
  392.                                         case SCAN_NODIALTONE:
  393.  
  394.                                             if(!FlowInfo . NoDialTone)
  395.                                             {
  396.                                                 FlowInfo . NoDialTone    = TRUE;
  397.                                                 FlowInfo . Changed    = TRUE;
  398.                                             }
  399.  
  400.                                             break;
  401.  
  402.                                             /* Modem accepted a command. */
  403.  
  404.                                         case SCAN_OK:
  405.  
  406.                                             if(!FlowInfo . Ok)
  407.                                             {
  408.                                                 FlowInfo . Ok        = TRUE;
  409.                                                 FlowInfo . Changed    = TRUE;
  410.                                             }
  411.  
  412.                                             break;
  413.  
  414.                                         default:
  415.  
  416.                                             if(!FlowInfo . Signature)
  417.                                             {
  418.                                                 FlowInfo . Signature    = i;
  419.                                                 FlowInfo . Changed    = TRUE;
  420.                                             }
  421.  
  422.                                             break;
  423.                                     }
  424.                                 }
  425.                             }
  426.                         }
  427.                     }
  428.  
  429.                     if(MatchMade)
  430.                         FlowCount++;
  431.                     else
  432.                     {
  433.                         if(FlowCount)
  434.                         {
  435.                             FlowCount = 0;
  436.  
  437.                             memset(AttentionCount,0,sizeof(AttentionCount));
  438.                         }
  439.                         else
  440.                             break;
  441.                     }
  442.                 }
  443.                 while(!FlowCount);
  444.             }
  445.         }
  446.     }
  447.     while(--Size);
  448. }
  449.  
  450.     /* StripSequence():
  451.      *
  452.      *    Strips a string from ESC and CSI introduced control
  453.      *    sequences.
  454.      */
  455.  
  456. STATIC LONG __regargs
  457. StripSequence(STRPTR Src,STRPTR Dst,LONG Length)
  458. {
  459.     STATIC BYTE    HasESC    = FALSE,
  460.             HasCSI    = FALSE;
  461.     LONG        Size    = 0;
  462.  
  463.     while(Length--)
  464.     {
  465.         if(HasESC)
  466.         {
  467.             if(*Src == '[')
  468.             {
  469.                 HasESC = FALSE;
  470.                 HasCSI = TRUE;
  471.             }
  472.             else
  473.             {
  474.                 if(*Src >= '0')
  475.                     HasESC = FALSE;
  476.             }
  477.  
  478.             Src++;
  479.  
  480.             continue;
  481.         }
  482.  
  483.         if(HasCSI)
  484.         {
  485.             if(*Src >= '@')
  486.                 HasCSI = FALSE;
  487.  
  488.             Src++;
  489.  
  490.             continue;
  491.         }
  492.  
  493.         switch(*Src)
  494.         {
  495.             case CAN:
  496.             case SUB:
  497.  
  498.                 HasESC = HasCSI = FALSE;
  499.                 break;
  500.  
  501.             case '\r':
  502.  
  503.                 break;
  504.  
  505.             case ESC:
  506.  
  507.                 HasESC = TRUE;
  508.                 break;
  509.  
  510.             case CSI:
  511.  
  512.                 HasCSI = TRUE;
  513.                 break;
  514.  
  515.             default:
  516.  
  517.                 if(IsPrintable[*Src])
  518.                 {
  519.                     *Dst++ = *Src;
  520.  
  521.                     Size++;
  522.                 }
  523.  
  524.                 break;
  525.         }
  526.  
  527.         Src++;
  528.     }
  529.  
  530.     return(Size);
  531. }
  532.  
  533.     /* ConOutputPrinter(STRPTR Buffer,LONG Size):
  534.      *
  535.      *    Raw text output routine, printer capture flavour.
  536.      */
  537.  
  538. STATIC VOID
  539. ConOutputPrinter(STRPTR Buffer,LONG Size)
  540. {
  541.     if(FWrite(PrinterCapture,Buffer,Size,1) != 1)
  542.     {
  543.         BlockWindows();
  544.  
  545.         if(!MyEasyRequest(NULL,LocaleString(MSG_CONSOLE_ERROR_WRITING_TO_PRINTER_TXT),LocaleString(MSG_CONSOLE_IGNORE_CLOSE_PRINTER_TXT)))
  546.             ClosePrinterCapture(TRUE);
  547.  
  548.         ReleaseWindows();
  549.     }
  550. }
  551.  
  552.     /* ConOutputGFX(STRPTR Buffer,LONG Size):
  553.      *
  554.      *    Raw text output routine, GFX text flavour.
  555.      */
  556.  
  557. STATIC VOID
  558. ConOutputGFX(STRPTR Buffer,LONG Size)
  559. {
  560.     register WORD Offset;
  561.  
  562.         /* Do we still have a character in the
  563.          * magnificient buffer?
  564.          */
  565.  
  566.     while(Size)
  567.     {
  568.             /* Cursor is positioned at
  569.              * the right hand side of the
  570.              * display. If auto-wrap is
  571.              * enabled, perform some
  572.              * kind of CR/LF, else leave
  573.              * the cursor where it is and
  574.              * quit the show.
  575.              */
  576.  
  577.         if(CursorX > LastPrintableColumn)
  578.         {
  579.                 /* Wrap cursor. */
  580.  
  581.             if(Config -> EmulationConfig -> LineWrap)
  582.             {
  583.                     /* Move to beginning of next line. */
  584.  
  585.                 CursorX = 0;
  586.  
  587.                 DownLine();
  588.  
  589.                     /* Reposition cursor, don't redraw it. */
  590.  
  591.                 RepositionCursor();
  592.             }
  593.             else
  594.             {
  595.                     /* Stop the cursor. */
  596.  
  597.                 CursorX = LastPrintableColumn;
  598.  
  599.                     /* Make it reappear. */
  600.  
  601.                 RepositionCursor();
  602.  
  603.                 return;
  604.             }
  605.         }
  606.  
  607.         if((Offset = LastPrintableColumn + 1 - CursorX) > Size)
  608.             Offset = Size;
  609.  
  610.         if(Config -> EmulationConfig -> InsertMode)
  611.         {
  612.             RasterShiftChar(Offset);
  613.  
  614.             ScrollLineShiftChar(Offset);
  615.  
  616.             ShiftChar(Offset);
  617.         }
  618.  
  619.         RasterPutString(Buffer,Offset);
  620.  
  621.         ScrollLinePutString(Offset);
  622.  
  623.         if(FontScalingRequired)
  624.             PrintScaled(Buffer,Offset,CurrentFontScale);
  625.         else
  626.             GfxText(RPort,Buffer,Offset);
  627.  
  628.         Buffer    += Offset;
  629.  
  630.         Size    -= Offset;
  631.  
  632.         CursorX    += Offset;
  633.     }
  634.  
  635.     RepositionCursor();
  636. }
  637.  
  638.     /* ConOutputNormal(STRPTR Buffer,LONG Size):
  639.      *
  640.      *    Raw text output routine, normal text flavour.
  641.      */
  642.  
  643. STATIC VOID
  644. ConOutputNormal(STRPTR Buffer,LONG Size)
  645. {
  646.     register WORD Offset;
  647.  
  648.     while(Size)
  649.     {
  650.         if(CursorX > LastPrintableColumn)
  651.         {
  652.             if(Config -> EmulationConfig -> LineWrap)
  653.             {
  654.                 CursorX = 0;
  655.  
  656.                 DownLine();
  657.  
  658.                 RepositionCursor();
  659.             }
  660.             else
  661.             {
  662.                 CursorX = LastPrintableColumn;
  663.  
  664.                 RepositionCursor();
  665.  
  666.                 return;
  667.             }
  668.         }
  669.  
  670.         if((Offset = LastPrintableColumn + 1 - CursorX) > Size)
  671.             Offset = Size;
  672.  
  673.         if(Config -> EmulationConfig -> InsertMode)
  674.         {
  675.             RasterShiftChar(Offset);
  676.  
  677.             ScrollLineShiftChar(Offset);
  678.  
  679.             ShiftChar(Offset);
  680.         }
  681.  
  682.         RasterPutString(Buffer,Offset);
  683.  
  684.         ScrollLinePutString(Offset);
  685.  
  686.         if(FontScalingRequired)
  687.             PrintScaled(Buffer,Offset,CurrentFontScale);
  688.         else
  689.             Text(RPort,Buffer,Offset);
  690.  
  691.         Buffer    += Offset;
  692.  
  693.         Size    -= Offset;
  694.  
  695.         CursorX    += Offset;
  696.     }
  697.  
  698.     RepositionCursor();
  699. }
  700.  
  701.     /* ConProcessUpdate():
  702.      *
  703.      *    Choose the right console data processing routine.
  704.      */
  705.  
  706. VOID
  707. ConProcessUpdate(VOID)
  708. {
  709.     Forbid();
  710.  
  711.     if(XEmulatorBase && Config -> TerminalConfig -> EmulationMode == EMULATION_EXTERNAL)
  712.     {
  713.         if(ReceiveTable)
  714.             ConProcessData = ConProcessDataTransExternal;
  715.         else
  716.             ConProcessData = ConProcessDataExternal;
  717.     }
  718.     else
  719.     {
  720.         if(Config -> SerialConfig -> StripBit8)
  721.         {
  722.             if(Config -> TerminalConfig -> EmulationMode == EMULATION_HEX)
  723.                 ConProcessData = ConProcessDataHex7;
  724.             else
  725.                 ConProcessData = ConProcessData7;
  726.         }
  727.         else
  728.         {
  729.             if(Config -> TerminalConfig -> EmulationMode == EMULATION_HEX)
  730.                 ConProcessData = ConProcessDataHex8;
  731.             else
  732.                 ConProcessData = ConProcessData8;
  733.         }
  734.     }
  735.  
  736.     Permit();
  737. }
  738.  
  739.     /* ConOutputUpdate():
  740.      *
  741.      *    Choose the right raw text output routine for the job.
  742.      */
  743.  
  744. VOID
  745. ConOutputUpdate()
  746. {
  747.     Forbid();
  748.  
  749.     if(BufferFrozen)
  750.     {
  751.         if(FileCapture)
  752.         {
  753.             if(PrinterCapture)
  754.             {
  755.                 if(Config -> CaptureConfig -> CaptureFilterMode)
  756.                     CaptureData = CaptureFilteredTo_File_Printer;
  757.                 else
  758.                     CaptureData = CaptureRawTo_File_Printer;
  759.             }
  760.             else
  761.             {
  762.                 if(Config -> CaptureConfig -> CaptureFilterMode)
  763.                     CaptureData = CaptureFilteredTo_File;
  764.                 else
  765.                     CaptureData = CaptureRawTo_File;
  766.             }
  767.         }
  768.         else
  769.         {
  770.             if(PrinterCapture)
  771.             {
  772.                 if(Config -> CaptureConfig -> CaptureFilterMode)
  773.                     CaptureData = CaptureFilteredTo_Printer;
  774.                 else
  775.                     CaptureData = CaptureRawTo_Printer;
  776.             }
  777.             else
  778.                 CaptureData = NULL;
  779.         }
  780.     }
  781.     else
  782.     {
  783.         if(FileCapture)
  784.         {
  785.             if(PrinterCapture)
  786.             {
  787.                 if(Config -> CaptureConfig -> CaptureFilterMode)
  788.                     CaptureData = CaptureFilteredTo_Buffer_File_Printer;
  789.                 else
  790.                     CaptureData = CaptureRawTo_Buffer_File_Printer;
  791.             }
  792.             else
  793.             {
  794.                 if(Config -> CaptureConfig -> CaptureFilterMode)
  795.                     CaptureData = CaptureFilteredTo_Buffer_File;
  796.                 else
  797.                     CaptureData = CaptureRawTo_Buffer_File;
  798.             }
  799.         }
  800.         else
  801.         {
  802.             if(PrinterCapture)
  803.             {
  804.                 if(Config -> CaptureConfig -> CaptureFilterMode)
  805.                     CaptureData = CaptureFilteredTo_Buffer_Printer;
  806.                 else
  807.                     CaptureData = CaptureRawTo_Buffer_Printer;
  808.             }
  809.             else
  810.             {
  811.                 if(Config -> CaptureConfig -> CaptureFilterMode)
  812.                     CaptureData = CaptureFilteredTo_Buffer;
  813.                 else
  814.                     CaptureData = CaptureRawTo_Buffer;
  815.             }
  816.         }
  817.     }
  818.  
  819.     if(ControllerActive)
  820.         ConOutput = ConOutputPrinter;
  821.     else
  822.     {
  823.         if(CurrentFont == GFX)
  824.             ConOutput = ConOutputGFX;
  825.         else
  826.             ConOutput = ConOutputNormal;
  827.     }
  828.  
  829.     if(ReceiveTable)
  830.         ConDump = ConTransWrite;
  831.     else
  832.         ConDump = ConOutput;
  833.  
  834.     Permit();
  835. }
  836.  
  837.     /* ConFontScaleUpdate():
  838.      *
  839.      *    Choose the right font scale for the job.
  840.      */
  841.  
  842. VOID
  843. ConFontScaleUpdate()
  844. {
  845.     CurrentFontScale    = RasterAttr[CursorY];
  846.     FontScalingRequired    = FALSE;
  847.     CharCellNominator    = 1;
  848.  
  849.     if(CurrentCharWidth == SCALE_HALF)
  850.         CharCellDenominator = 2;
  851.     else
  852.         CharCellDenominator = 1;
  853.  
  854.     if(CurrentFontScale == SCALE_ATTR_NORMAL)
  855.     {
  856.         if(CurrentCharWidth == SCALE_HALF)
  857.         {
  858.                 // Half of normal width
  859.  
  860.             LastPrintableColumn    = (LastColumn + 1) * 2 - 1;
  861.             LastPrintablePixel     = (LastPixel + 1) * 2 - 1;
  862.             FontScalingRequired    = TRUE;
  863.         }
  864.         else
  865.         {
  866.                 // Normal width
  867.  
  868.             LastPrintableColumn    = LastColumn;
  869.             LastPrintablePixel    = LastPixel;
  870.         }
  871.     }
  872.     else
  873.     {
  874.         if(CurrentCharWidth == SCALE_HALF)
  875.         {
  876.                 // Half of double width
  877.  
  878.             LastPrintableColumn    = LastColumn;
  879.             LastPrintablePixel    = LastPixel;
  880.         }
  881.         else
  882.         {
  883.                 // Double width
  884.  
  885.             LastPrintableColumn    = ((LastColumn + 1) / 2) - 1;
  886.             LastPrintablePixel    = ((LastPixel + 1) / 2) - 1;
  887.             FontScalingRequired    = TRUE;
  888.         }
  889.     }
  890. }
  891.  
  892.     /* ConTransWrite(STRPTR Buffer,LONG Size):
  893.      *
  894.      *    Frontend for ConWrite(), including character translation.
  895.      */
  896.  
  897. VOID
  898. ConTransWrite(STRPTR Buffer,LONG Size)
  899. {
  900.     struct TranslationHandle    Handle;
  901.     UBYTE                LocalBuffer[256];
  902.  
  903.         /* Set up for translation. */
  904.  
  905.     ConTranslateSetup(&Handle,Buffer,Size,LocalBuffer,256,ReceiveTable);
  906.  
  907.         /* Process and output the data. */
  908.  
  909.     while(Size = ConTranslateBuffer(&Handle))
  910.         (* ConOutput)(LocalBuffer,Size);
  911. }
  912.  
  913.     /* ConProcessDataTransExternal(register STRPTR String,register LONG Size):
  914.      *
  915.      *    Process data, external emulation including translation flavour.
  916.      */
  917.  
  918. VOID
  919. ConProcessDataTransExternal(register STRPTR String,register LONG Size)
  920. {
  921.     struct TranslationHandle Handle;
  922.  
  923.         /* Set up for translation. */
  924.  
  925.     ConTranslateSetup(&Handle,String,Size,ConTempBuffer,256,ReceiveTable);
  926.  
  927.     if(StripBuffer)
  928.     {
  929.         register LONG Len;
  930.  
  931.             /* Process and output the data. */
  932.  
  933.         while(Size = ConTranslateBuffer(&Handle))
  934.         {
  935.             XEmulatorWrite(XEM_IO,ConTempBuffer,Size);
  936.  
  937.             XEM_HostData . Source        = ConTempBuffer;
  938.             XEM_HostData . Destination    = StripBuffer;
  939.  
  940.             if(Len = XEmulatorHostMon(XEM_IO,&XEM_HostData,Size))
  941.             {
  942.                 if(CaptureData)
  943.                     (*CaptureData)(StripBuffer,Len);
  944.             }
  945.         }
  946.     }
  947.     else
  948.     {
  949.             /* Process and output the data. */
  950.  
  951.         while(Size = ConTranslateBuffer(&Handle))
  952.             XEmulatorWrite(XEM_IO,ConTempBuffer,Size);
  953.     }
  954. }
  955.  
  956.     /* ConProcessDataExternal(register STRPTR String,register LONG Size):
  957.      *
  958.      *    Process data, external emulation flavour.
  959.      */
  960.  
  961. VOID
  962. ConProcessDataExternal(register STRPTR String,register LONG Size)
  963. {
  964.     XEmulatorWrite(XEM_IO,String,Size);
  965.  
  966.         /* Build another string to contain
  967.          * the pure ASCII contents, i.e.
  968.          * not including any ESC control
  969.          * sequences.
  970.          */
  971.  
  972.     if(StripBuffer)
  973.     {
  974.         register LONG Len;
  975.  
  976.         XEM_HostData . Source        = String;
  977.         XEM_HostData . Destination    = StripBuffer;
  978.  
  979.         if(Len = XEmulatorHostMon(XEM_IO,&XEM_HostData,Size))
  980.         {
  981.             if(CaptureData)
  982.                 (*CaptureData)(StripBuffer,Len);
  983.         }
  984.     }
  985. }
  986.  
  987.     /* ConProcessData7(register STRPTR String,register LONG Size):
  988.      *
  989.      *    Process data, 7 bit flavour.
  990.      */
  991.  
  992. VOID
  993. ConProcessData7(register STRPTR String,register LONG Size)
  994. {
  995.     register LONG    Len = 0;
  996.     register UBYTE    c;
  997.  
  998. #if 0
  999.         // Check for prescroll/jump scroll
  1000.  
  1001.     if(CursorY == Bottom && Bottom > 0)
  1002.     {
  1003.             // The maximum number of line feeds we need to look for
  1004.  
  1005.         register WORD Max = MAX(Config -> EmulationConfig -> MaxJump,Config -> EmulationConfig -> MaxScroll);
  1006.  
  1007.             // Any prescroll/jump scroll action wanted?
  1008.  
  1009.         if(Max)
  1010.         {
  1011.             register WORD     Count    = Size,
  1012.                      Lines    = 0;
  1013.             register UBYTE    *Buffer    = String;
  1014.  
  1015.                 // Count the number of line feeds
  1016.  
  1017.             while(Count--)
  1018.             {
  1019.                 if((*Buffer++ & 0x7F) == '\n')
  1020.                 {
  1021.                     if(++Lines == Max)
  1022.                         break;
  1023.                 }
  1024.             }
  1025.  
  1026.                 // Ok, so we have found something
  1027.  
  1028.             if(Lines)
  1029.             {
  1030.                 register WORD Scroll,TotalLines;
  1031.  
  1032.                     // Scroll by default?
  1033.  
  1034.                 if(Scroll = Config -> EmulationConfig -> MaxJump)
  1035.                 {
  1036.                         // If there is more, use it
  1037.  
  1038.                     if(Lines > Scroll)
  1039.                         Scroll = Lines;
  1040.                 }
  1041.                 else
  1042.                     Scroll = Lines;
  1043.  
  1044.                     // How tall is the current scroll region?
  1045.  
  1046.                 TotalLines = Bottom - Top + 1;
  1047.  
  1048.                     // Don't scroll more than the entire screenful
  1049.  
  1050.                 if(Scroll > TotalLines)
  1051.                     Scroll = TotalLines;
  1052.  
  1053.                     // Is it worth scrolling?
  1054.  
  1055.                 if(Scroll > 1)
  1056.                 {
  1057.                     LONG OldBack = BackgroundPen;
  1058.  
  1059.                     if(OldBack)
  1060.                     {
  1061.                         BackgroundPen = 0;
  1062.  
  1063.                         UpdatePens();
  1064.                     }
  1065.  
  1066.                         // Scroll the region...
  1067.  
  1068.                     ScrollRegion(Scroll);
  1069.  
  1070.                         // Reposition the cursor
  1071.  
  1072.                     if(CursorY > Scroll)
  1073.                         CursorY -= Scroll;
  1074.                     else
  1075.                         CursorY = 0;
  1076.  
  1077.                     RepositionCursor();
  1078.  
  1079.                     if(OldBack)
  1080.                     {
  1081.                         BackgroundPen = OldBack;
  1082.  
  1083.                         UpdatePens();
  1084.                     }
  1085.                 }
  1086.             }
  1087.         }
  1088.     }
  1089. #endif
  1090.  
  1091.         /* If still parsing a sequence,
  1092.          * continue with it.
  1093.          */
  1094.  
  1095.     if(InSequence)
  1096.     {
  1097.         while(Size--)
  1098.         {
  1099.             c = *String++ & 0x7F;
  1100.  
  1101.             if(!(*AbortTable[c])(c))
  1102.             {
  1103.                 InSequence = FALSE;
  1104.  
  1105.                 break;
  1106.             }
  1107.         }
  1108.     }
  1109.  
  1110.         /* Check which font we are in, if other than Topaz
  1111.          * the only invalid char is a Null (0) which will
  1112.          * display as a space if let to continue.
  1113.          */
  1114.  
  1115.     if(Config -> TerminalConfig -> FontMode == FONT_STANDARD)
  1116.     {
  1117.         while(Size-- > 0)
  1118.         {
  1119.             if(IsPrintable[c = *String++ & 0x7F])
  1120.             {
  1121.                     /* This character is associated with a
  1122.                      * special function (bell, xon, xoff, etc.).
  1123.                      */
  1124.  
  1125.                 if(SpecialTable[c])
  1126.                 {
  1127.                     if(Len)
  1128.                     {
  1129.                         (*ConDump)(ConTempBuffer,Len);
  1130.  
  1131.                         Len = 0;
  1132.                     }
  1133.  
  1134.                         /* Does this character start
  1135.                          * a control sequence?
  1136.                          */
  1137.  
  1138.                     if(InSequence = (*SpecialTable[c])(c))
  1139.                     {
  1140.                         while(Size-- > 0)
  1141.                         {
  1142.                             c = *String++ & 0x7F;
  1143.  
  1144.                             if(!(*AbortTable[c])(c))
  1145.                             {
  1146.                                 InSequence = FALSE;
  1147.  
  1148.                                 break;
  1149.                             }
  1150.                         }
  1151.                     }
  1152.                 }
  1153.                 else
  1154.                 {
  1155.                         /* Put the character into the buffer
  1156.                          * and flush it if necessary.
  1157.                          */
  1158.  
  1159.                     ConTempBuffer[Len] = c;
  1160.  
  1161.                     if(Len++ == 512)
  1162.                     {
  1163.                         (*ConDump)(ConTempBuffer,Len);
  1164.  
  1165.                         Len = 0;
  1166.                     }
  1167.                 }
  1168.             }
  1169.         }
  1170.     }
  1171.     else
  1172.     {
  1173.         while(Size-- > 0)
  1174.         {
  1175.             if(c = (*String++ & 0x7F))
  1176.             {
  1177.                     /* This character is associated with a
  1178.                      * special function (bell, xon, xoff, etc.).
  1179.                      */
  1180.  
  1181.                 if(SpecialTable[c])
  1182.                 {
  1183.                     if(Len)
  1184.                     {
  1185.                         (*ConDump)(ConTempBuffer,Len);
  1186.  
  1187.                         Len = 0;
  1188.                     }
  1189.  
  1190.                     if(InSequence = (*SpecialTable[c])(c))
  1191.                     {
  1192.                         while(Size-- > 0)
  1193.                         {
  1194.                             c = *String++ & 0x7F;
  1195.  
  1196.                             if(!(*AbortTable[c])(c))
  1197.                             {
  1198.                                 InSequence = FALSE;
  1199.  
  1200.                                 break;
  1201.                             }
  1202.                         }
  1203.                     }
  1204.                 }
  1205.                 else
  1206.                 {
  1207.                         /* Put the character into the buffer
  1208.                          * and flush it if necessary.
  1209.                          */
  1210.  
  1211.                     ConTempBuffer[Len] = c;
  1212.  
  1213.                     if(Len++ == 512)
  1214.                     {
  1215.                         (*ConDump)(ConTempBuffer,Len);
  1216.  
  1217.                         Len = 0;
  1218.                     }
  1219.                 }
  1220.             }
  1221.         }
  1222.     }
  1223.  
  1224.     if(Len)
  1225.         (*ConDump)(ConTempBuffer,Len);
  1226. }
  1227.  
  1228.     /* ConProcessData8(register STRPTR String,register LONG Size):
  1229.      *
  1230.      *    Process data, 8 bit flavour.
  1231.      */
  1232.  
  1233. VOID
  1234. ConProcessData8(register STRPTR String,register LONG Size)
  1235. {
  1236.     register LONG    Len = 0;
  1237.     register UBYTE    c;
  1238.  
  1239. #if 0
  1240.         // Check for prescroll/jump scroll
  1241.  
  1242.     if(CursorY == Bottom && Bottom > 0)
  1243.     {
  1244.             // The maximum number of line feeds we need to look for
  1245.  
  1246.         register WORD Max = MAX(Config -> EmulationConfig -> MaxJump,Config -> EmulationConfig -> MaxScroll);
  1247.  
  1248.             // Any prescroll/jump scroll action wanted?
  1249.  
  1250.         if(Max)
  1251.         {
  1252.             register WORD     Count    = Size,
  1253.                      Lines    = 0;
  1254.             register UBYTE    *Buffer    = String;
  1255.  
  1256.                 // Count the number of line feeds
  1257.  
  1258.             while(Count--)
  1259.             {
  1260.                 if(*Buffer++ == '\n')
  1261.                 {
  1262.                     if(++Lines == Max)
  1263.                         break;
  1264.                 }
  1265.             }
  1266.  
  1267.                 // Ok, so we have found something
  1268.  
  1269.             if(Lines)
  1270.             {
  1271.                 register WORD Scroll,TotalLines;
  1272.  
  1273.                     // Scroll by default?
  1274.  
  1275.                 if(Scroll = Config -> EmulationConfig -> MaxJump)
  1276.                 {
  1277.                         // If there is more, use it
  1278.  
  1279.                     if(Lines > Scroll)
  1280.                         Scroll = Lines;
  1281.                 }
  1282.                 else
  1283.                     Scroll = Lines;
  1284.  
  1285.                     // How tall is the current scroll region?
  1286.  
  1287.                 TotalLines = Bottom - Top + 1;
  1288.  
  1289.                     // Don't scroll more than the entire screenful
  1290.  
  1291.                 if(Scroll > TotalLines)
  1292.                     Scroll = TotalLines;
  1293.  
  1294.                     // Is it worth scrolling?
  1295.  
  1296.                 if(Scroll > 1)
  1297.                 {
  1298.                     LONG OldBack = BackgroundPen;
  1299.  
  1300.                     if(OldBack)
  1301.                     {
  1302.                         BackgroundPen = 0;
  1303.  
  1304.                         UpdatePens();
  1305.                     }
  1306.  
  1307.                         // Scroll the region...
  1308.  
  1309.                     ScrollRegion(Scroll);
  1310.  
  1311.                         // Reposition the cursor
  1312.  
  1313.                     if(CursorY > Scroll)
  1314.                         CursorY -= Scroll;
  1315.                     else
  1316.                         CursorY = 0;
  1317.  
  1318.                     RepositionCursor();
  1319.  
  1320.                     if(OldBack)
  1321.                     {
  1322.                         BackgroundPen = OldBack;
  1323.  
  1324.                         UpdatePens();
  1325.                     }
  1326.                 }
  1327.             }
  1328.         }
  1329.     }
  1330. #endif
  1331.  
  1332.     if(InSequence)
  1333.     {
  1334.         while(Size--)
  1335.         {
  1336.             c = *String++;
  1337.  
  1338.             if(!(*AbortTable[c])(c))
  1339.             {
  1340.                 InSequence = FALSE;
  1341.  
  1342.                 break;
  1343.             }
  1344.         }
  1345.     }
  1346.  
  1347.     if(Config -> TerminalConfig -> FontMode == FONT_STANDARD)
  1348.     {
  1349.         while(Size-- > 0)
  1350.         {
  1351.             if(IsPrintable[c = *String++])
  1352.             {
  1353.                 if(SpecialTable[c])
  1354.                 {
  1355.                     if(Len)
  1356.                     {
  1357.                         (*ConDump)(ConTempBuffer,Len);
  1358.  
  1359.                         Len = 0;
  1360.                     }
  1361.  
  1362.                     if(InSequence = (*SpecialTable[c])(c))
  1363.                     {
  1364.                         while(Size-- > 0)
  1365.                         {
  1366.                             c = *String++;
  1367.  
  1368.                             if(!(*AbortTable[c])(c))
  1369.                             {
  1370.                                 InSequence = FALSE;
  1371.  
  1372.                                 break;
  1373.                             }
  1374.                         }
  1375.                     }
  1376.                 }
  1377.                 else
  1378.                 {
  1379.                     ConTempBuffer[Len] = c;
  1380.  
  1381.                     if(Len++ == 512)
  1382.                     {
  1383.                         (*ConDump)(ConTempBuffer,Len);
  1384.  
  1385.                         Len = 0;
  1386.                     }
  1387.                 }
  1388.             }
  1389.         }
  1390.     }
  1391.     else
  1392.     {
  1393.         while(Size-- > 0)
  1394.         {
  1395.             if(c = *String++)
  1396.             {
  1397.                 if(SpecialTable[c])
  1398.                 {
  1399.                     if(Len)
  1400.                     {
  1401.                         (*ConDump)(ConTempBuffer,Len);
  1402.  
  1403.                         Len = 0;
  1404.                     }
  1405.  
  1406.                     if(InSequence = (*SpecialTable[c])(c))
  1407.                     {
  1408.                         while(Size-- > 0)
  1409.                         {
  1410.                             c = *String++;
  1411.  
  1412.                             if(!(*AbortTable[c])(c))
  1413.                             {
  1414.                                 InSequence = FALSE;
  1415.  
  1416.                                 break;
  1417.                             }
  1418.                         }
  1419.                     }
  1420.                 }
  1421.                 else
  1422.                 {
  1423.                     ConTempBuffer[Len] = c;
  1424.  
  1425.                     if(Len++ == 512)
  1426.                     {
  1427.                         (*ConDump)(ConTempBuffer,Len);
  1428.  
  1429.                         Len = 0;
  1430.                     }
  1431.                 }
  1432.             }
  1433.         }
  1434.     }
  1435.  
  1436.     if(Len)
  1437.         (*ConDump)(ConTempBuffer,Len);
  1438. }
  1439.  
  1440.     /* ConProcessDataHex7(register STRPTR String,register LONG Size):
  1441.      *
  1442.      *    Process data, hex mode flavour, seven bits.
  1443.      */
  1444.  
  1445. VOID
  1446. ConProcessDataHex7(register STRPTR String,register LONG Size)
  1447. {
  1448.     UBYTE    DummyBuffer[40],c;
  1449.     LONG    Fit,Spaces,Current;
  1450.  
  1451.         /* How many characters will fit into the line? */
  1452.  
  1453.     Fit    = (LastColumn + 1) / 4;
  1454.  
  1455.         /* Which position are we currently in? */
  1456.  
  1457.     Current    = CursorX / 3;
  1458.  
  1459.         /* Weird cursor position? */
  1460.  
  1461.     if(Current >= Fit || (CursorX % 3))
  1462.     {
  1463.         ConProcessData7("\r\n",2);
  1464.  
  1465.         Current = 0;
  1466.     }
  1467.  
  1468.         /* Check the font type. */
  1469.  
  1470.     if(Config -> TerminalConfig -> FontMode == FONT_STANDARD)
  1471.     {
  1472.         while(Size-- > 0)
  1473.         {
  1474.             c = (*String++) & 0x7F;
  1475.  
  1476.             Spaces = (Fit - Current) * 3 + Current - 3;
  1477.  
  1478.             if(c > ' ' && c < 127)
  1479.                 SPrintf(DummyBuffer,"%02lx \33[%ldC%lc\33[%ldD",c,Spaces,c,Spaces + 1);
  1480.             else
  1481.                 SPrintf(DummyBuffer,"%02lx \33[%ldC.\33[%ldD",c,Spaces,Spaces + 1);
  1482.  
  1483.             ConProcessData7(DummyBuffer,strlen(DummyBuffer));
  1484.  
  1485.             if(Current++ == Fit - 1)
  1486.             {
  1487.                 Current = 0;
  1488.  
  1489.                 ConProcessData7("\r\n",2);
  1490.             }
  1491.         }
  1492.     }
  1493.     else
  1494.     {
  1495.         while(Size-- > 0)
  1496.         {
  1497.             c = (*String++) & 0x7F;
  1498.  
  1499.             Spaces = (Fit - Current) * 3 + Current - 3;
  1500.  
  1501.             if(c && c != ' ')
  1502.                 SPrintf(DummyBuffer,"%02lx \33[%ldC%lc\33[%ldD",c,Spaces,c,Spaces + 1);
  1503.             else
  1504.                 SPrintf(DummyBuffer,"%02lx \33[%ldC.\33[%ldD",c,Spaces,Spaces + 1);
  1505.  
  1506.             ConProcessData7(DummyBuffer,strlen(DummyBuffer));
  1507.  
  1508.             if(Current++ == Fit - 1)
  1509.             {
  1510.                 Current = 0;
  1511.  
  1512.                 ConProcessData7("\r\n",2);
  1513.             }
  1514.         }
  1515.     }
  1516. }
  1517.  
  1518.     /* ConProcessDataHex8(register STRPTR String,register LONG Size):
  1519.      *
  1520.      *    Process data, hex mode flavour, eight bits.
  1521.      */
  1522.  
  1523. VOID
  1524. ConProcessDataHex8(register STRPTR String,register LONG Size)
  1525. {
  1526.     UBYTE    DummyBuffer[40],c;
  1527.     LONG    Fit,Spaces,Current;
  1528.  
  1529.         /* How many characters will fit into the line? */
  1530.  
  1531.     Fit    = (LastColumn + 1) / 4;
  1532.  
  1533.         /* Which position are we currently in? */
  1534.  
  1535.     Current    = CursorX / 3;
  1536.  
  1537.         /* Weird cursor position? */
  1538.  
  1539.     if(Current >= Fit || (CursorX % 3))
  1540.     {
  1541.         ConProcessData8("\r\n",2);
  1542.  
  1543.         Current = 0;
  1544.     }
  1545.  
  1546.         /* Check the font type. */
  1547.  
  1548.     if(Config -> TerminalConfig -> FontMode == FONT_STANDARD)
  1549.     {
  1550.         while(Size-- > 0)
  1551.         {
  1552.             c = *String++;
  1553.  
  1554.             Spaces = (Fit - Current) * 3 + Current - 3;
  1555.  
  1556.             if((c > ' ' && c < 127) || c > 160)
  1557.                 SPrintf(DummyBuffer,"%02lx \33[%ldC%lc\33[%ldD",c,Spaces,c,Spaces + 1);
  1558.             else
  1559.                 SPrintf(DummyBuffer,"%02lx \33[%ldC.\33[%ldD",c,Spaces,Spaces + 1);
  1560.  
  1561.             ConProcessData8(DummyBuffer,strlen(DummyBuffer));
  1562.  
  1563.             if(Current++ == Fit - 1)
  1564.             {
  1565.                 Current = 0;
  1566.  
  1567.                 ConProcessData8("\r\n",2);
  1568.             }
  1569.         }
  1570.     }
  1571.     else
  1572.     {
  1573.         while(Size-- > 0)
  1574.         {
  1575.             c = *String++;
  1576.  
  1577.             Spaces = (Fit - Current) * 3 + Current - 3;
  1578.  
  1579.             if(c && c != ' ')
  1580.                 SPrintf(DummyBuffer,"%02lx \33[%ldC%lc\33[%ldD",c,Spaces,c,Spaces + 1);
  1581.             else
  1582.                 SPrintf(DummyBuffer,"%02lx \33[%ldC.\33[%ldD",c,Spaces,Spaces + 1);
  1583.  
  1584.             ConProcessData8(DummyBuffer,strlen(DummyBuffer));
  1585.  
  1586.             if(Current++ == Fit - 1)
  1587.             {
  1588.                 Current = 0;
  1589.  
  1590.                 ConProcessData8("\r\n",2);
  1591.             }
  1592.         }
  1593.     }
  1594. }
  1595.  
  1596.     /* ConTransferHost(STRPTR Buffer,LONG Len):
  1597.      *
  1598.      *    Process data read from the serial line,
  1599.      *    special XPR flavour.
  1600.      */
  1601.  
  1602. VOID
  1603. ConTransferHost(STRPTR Buffer,LONG Len)
  1604. {
  1605.     Len = XProtocolHostMon(XprIO,Buffer,Len,SerialBufferSize);
  1606.  
  1607.     if(TransferWindow)
  1608.         TransferCleanup();
  1609.  
  1610.     if(Len)
  1611.         ConProcess(Buffer,Len);
  1612. }
  1613.  
  1614.     /* ConsoleCommand(STRPTR String):
  1615.      *
  1616.      *    Just like SerialCommand(), but addresses the local
  1617.      *    terminal side.
  1618.      */
  1619.  
  1620. VOID
  1621. ConsoleCommand(STRPTR String)
  1622. {
  1623.     STATIC UBYTE __far LocalBuffer[256];
  1624.  
  1625.     LONG    Count = 0,i,Len = strlen(String);
  1626.  
  1627.     BYTE    GotControl    = FALSE,
  1628.         GotEscape    = FALSE;
  1629.  
  1630.         /* Scan the string. */
  1631.  
  1632.     for(i = 0 ; i < Len ; i++)
  1633.     {
  1634.             /* We are looking for plain characters
  1635.              * and the control ('\') and escape
  1636.              * ('^') characters.
  1637.              */
  1638.  
  1639.         if(!GotControl && !GotEscape)
  1640.         {
  1641.                 /* Got a control character,
  1642.                  * the next byte will probably be
  1643.                  * a command sequence.
  1644.                  */
  1645.  
  1646.             if(String[i] == '\\')
  1647.             {
  1648.                 GotControl = TRUE;
  1649.  
  1650.                 continue;
  1651.             }
  1652.  
  1653.                 /* Got an escape character,
  1654.                  * the next byte will be some
  1655.                  * kind of control character
  1656.                  * (such as XON, XOF, bell, etc.).
  1657.                  */
  1658.  
  1659.             if(String[i] == '^')
  1660.             {
  1661.                 GotEscape = TRUE;
  1662.  
  1663.                 continue;
  1664.             }
  1665.  
  1666.                 /* This tells us to wait another
  1667.                  * second before continuing with
  1668.                  * the scanning.
  1669.                  */
  1670.  
  1671.             if(String[i] == '~')
  1672.                 continue;
  1673.  
  1674.                 /* Stuff the character into the
  1675.                  * buffer.
  1676.                  */
  1677.  
  1678.             LocalBuffer[Count++] = String[i];
  1679.         }
  1680.         else
  1681.         {
  1682.                 /* Convert the character to a control
  1683.                  * style character (^C, etc.).
  1684.                  */
  1685.  
  1686.             if(GotEscape)
  1687.             {
  1688.                 if(ToUpper(String[i]) >= 'A' && ToUpper(String[i]) <= '_')
  1689.                     LocalBuffer[Count++] = ToUpper(String[i]) - '@';
  1690.                 else
  1691.                     LocalBuffer[Count++] = String[i];
  1692.  
  1693.                 GotEscape = FALSE;
  1694.             }
  1695.  
  1696.                 /* The next character represents a command. */
  1697.  
  1698.             if(GotControl)
  1699.             {
  1700.                 switch(ToUpper(String[i]))
  1701.                 {
  1702.                         /* Translate code. */
  1703.  
  1704.                     case '*':
  1705.  
  1706.                         i++;
  1707.  
  1708.                         while(i < Len && String[i] == ' ')
  1709.                             i++;
  1710.  
  1711.                         if(i < Len)
  1712.                         {
  1713.                             UBYTE DummyBuffer[5],j = 0,Char;
  1714.  
  1715.                             if(String[i] >= '0' && String[i] <= '9')
  1716.                             {
  1717.                                 while(j < 3 && i < Len)
  1718.                                 {
  1719.                                     Char = String[i++];
  1720.  
  1721.                                     if(Char >= '0' && Char <= '9')
  1722.                                         DummyBuffer[j++] = Char;
  1723.                                     else
  1724.                                     {
  1725.                                         i--;
  1726.  
  1727.                                         break;
  1728.                                     }
  1729.                                 }
  1730.                             }
  1731.                             else
  1732.                             {
  1733.                                 while(j < 4 && i < Len)
  1734.                                 {
  1735.                                     Char = ToLower(String[i++]);
  1736.  
  1737.                                     if((Char >= '0' && Char <= '9') || (Char >= 'a' && Char <= 'z'))
  1738.                                         DummyBuffer[j++] = Char;
  1739.                                     else
  1740.                                     {
  1741.                                         i--;
  1742.  
  1743.                                         break;
  1744.                                     }
  1745.                                 }
  1746.                             }
  1747.  
  1748.                             DummyBuffer[j] = 0;
  1749.  
  1750.                             LocalBuffer[Count++] = NameToCode(DummyBuffer);
  1751.                         }
  1752.  
  1753.                         i--;
  1754.  
  1755.                         break;
  1756.  
  1757.                         /* Execute an AmigaDOS command. */
  1758.  
  1759.                     case 'D':
  1760.  
  1761.                         return;
  1762.  
  1763.                         /* Execute an ARexx command. */
  1764.  
  1765.                     case 'A':
  1766.  
  1767.                         return;
  1768.  
  1769.                         /* Add the control character ('\'). */
  1770.  
  1771.                     case '\\':
  1772.  
  1773.                         LocalBuffer[Count++] = '\\';
  1774.                         break;
  1775.  
  1776.                         /* This is a backspace. */
  1777.  
  1778.                     case 'B':
  1779.  
  1780.                         LocalBuffer[Count++] = '\b';
  1781.                         break;
  1782.  
  1783.                         /* This is a form feed. */
  1784.  
  1785.                     case 'F':
  1786.  
  1787.                         LocalBuffer[Count++] = '\f';
  1788.                         break;
  1789.  
  1790.                         /* This is a line feed. */
  1791.  
  1792.                     case 'N':
  1793.  
  1794.                         LocalBuffer[Count++] = '\n';
  1795.                         break;
  1796.  
  1797.                         /* Send the current password. */
  1798.  
  1799.                     case 'P':
  1800.  
  1801.                         break;
  1802.  
  1803.                         /* This is a carriage return. */
  1804.  
  1805.                     case 'R':
  1806.  
  1807.                         LocalBuffer[Count++] = '\r';
  1808.                         break;
  1809.  
  1810.                         /* This is a tab. */
  1811.  
  1812.                     case 'T':
  1813.  
  1814.                         LocalBuffer[Count++] = '\t';
  1815.                         break;
  1816.  
  1817.                         /* Send the current user name. */
  1818.  
  1819.                     case 'U':
  1820.  
  1821.                         break;
  1822.  
  1823.                         /* Send a break across the serial line. */
  1824.  
  1825.                     case 'X':
  1826.  
  1827.                         break;
  1828.  
  1829.                         /* Feed the contents of the
  1830.                          * clipboard into the input
  1831.                          * stream.
  1832.                          */
  1833.  
  1834.                     case 'I':
  1835.  
  1836.                         if(Count)
  1837.                             ConProcess(LocalBuffer,Count);
  1838.  
  1839.                         Count = LoadClip(LocalBuffer,256);
  1840.  
  1841.                         break;
  1842.  
  1843.                         /* Send a string to the clipboard. */
  1844.  
  1845.                     case 'G':
  1846.  
  1847.                         if(String[i + 1])
  1848.                             SaveClip(&String[i + 1],strlen(&String[i + 1]));
  1849.  
  1850.                         return;
  1851.  
  1852.                         /* Produce the escape character. */
  1853.  
  1854.                     case 'E':
  1855.  
  1856.                         LocalBuffer[Count++] = ESC;
  1857.                         break;
  1858.  
  1859.                         /* Call a menu item. */
  1860.  
  1861.                     case 'C':
  1862.  
  1863.                         break;
  1864.  
  1865.                         /* Stuff the character into the buffer. */
  1866.  
  1867.                     default:
  1868.  
  1869.                         LocalBuffer[Count++] = String[i];
  1870.                         break;
  1871.                 }
  1872.  
  1873.                 GotControl = FALSE;
  1874.             }
  1875.         }
  1876.  
  1877.             /* If the buffer is full, release it. */
  1878.  
  1879.         if(Count == 256)
  1880.         {
  1881.             ConProcess(LocalBuffer,Count);
  1882.  
  1883.             Count = 0;
  1884.         }
  1885.     }
  1886.  
  1887.     if(Count)
  1888.         ConProcess(LocalBuffer,Count);
  1889. }
  1890.  
  1891.     /* ConBypass(STRPTR String,LONG Size):
  1892.      *
  1893.      *    Bypass the `normal' ConOutput() data processing.
  1894.      */
  1895.  
  1896. VOID __regargs
  1897. ConBypass(STRPTR String,LONG Size)
  1898. {
  1899.     if(Size < 0)
  1900.         Size = strlen(String);
  1901.  
  1902.     if(Size > 0)
  1903.     {
  1904.         VOID (* ProcessData)(STRPTR,LONG);
  1905.  
  1906.         if(Config -> SerialConfig -> StripBit8)
  1907.             ProcessData = ConProcessData7;
  1908.         else
  1909.             ProcessData = ConProcessData8;
  1910.  
  1911.         ObtainSemaphore(&TerminalSemaphore);
  1912.  
  1913.         if(Marking)
  1914.             DropMarker();
  1915.  
  1916.         ClearCursor();
  1917.  
  1918.         (*ProcessData)(String,Size);
  1919.  
  1920.         DrawCursor();
  1921.  
  1922.         ReleaseSemaphore(&TerminalSemaphore);
  1923.     }
  1924. }
  1925.  
  1926.     /* ConProcess(STRPTR String,LONG Size):
  1927.      *
  1928.      *    Process the contents of a string to be sent to the
  1929.      *    console window.
  1930.      */
  1931.  
  1932. VOID
  1933. ConProcess(register STRPTR String,register LONG Size)
  1934. {
  1935.         /* Feed the flow filter. */
  1936.  
  1937.     if(UseFlow)
  1938.     {
  1939.         if(Config -> SerialConfig -> StripBit8)
  1940.             FlowFilter(String,Size,0x7F);
  1941.         else
  1942.             FlowFilter(String,Size,0xFF);
  1943.     }
  1944.  
  1945.         /* In quiet mode no characters are echoed to the
  1946.          * console window, they are just passed through
  1947.          * the data flow filter. Usually, this mode is
  1948.          * enabled by the dial panel.
  1949.          */
  1950.  
  1951.     if(!Quiet)
  1952.     {
  1953.             /* Capture the data. */
  1954.  
  1955.         if(CaptureData && Size > 0)
  1956.         {
  1957.             if(Config -> CaptureConfig -> ConvertChars && Config -> TerminalConfig -> FontMode != FONT_STANDARD)
  1958.             {
  1959.                 UBYTE     LocalBuffer[BUFFER_LINE_MAX];
  1960.  
  1961.                 UBYTE    *Src = String,
  1962.                     *Dst,
  1963.                      c;
  1964.  
  1965.                 ULONG     Count,Len = Size;
  1966.  
  1967.                 while(Len > 0)
  1968.                 {
  1969.                     Count = MIN(BUFFER_LINE_MAX,Len);
  1970.  
  1971.                     Len -= Count;
  1972.  
  1973.                     Dst = LocalBuffer;
  1974.  
  1975.                     do
  1976.                     {
  1977.                         if(c = ISOConversion[*Src++])
  1978.                             *Dst++ = c;
  1979.                         else
  1980.                             *Dst++ = (UBYTE)'·';
  1981.                     }
  1982.                     while(--Count > 0);
  1983.  
  1984.                     if((Count = (ULONG)Dst - (ULONG)&LocalBuffer[0]) > 0)
  1985.                         (*CaptureData)(LocalBuffer,Count);
  1986.                 }
  1987.             }
  1988.             else
  1989.                 (*CaptureData)(String,Size);
  1990.         }
  1991.  
  1992.             /* Remember the data. */
  1993.  
  1994.         if(RememberOutput)
  1995.             RememberOutputText(String,Size);
  1996.  
  1997.             /* Check the traps if necessary. */
  1998.  
  1999.         if(WatchTraps)
  2000.             TrapFilter(String,Size);
  2001.  
  2002.         if(Marking)
  2003.             DropMarker();
  2004.  
  2005.         if(TerminalQueue)
  2006.         {
  2007.             struct DataMsg *Msg;
  2008.  
  2009.             if(Msg = (struct DataMsg *)CreateMsgItem(sizeof(struct DataMsg) + Size))
  2010.             {
  2011.                 Msg -> Data = (APTR)(Msg + 1);
  2012.                 Msg -> Size = Size;
  2013.  
  2014.                 CopyMem(String,Msg -> Data,Msg -> Size);
  2015.  
  2016.                 PutMsgItem(TerminalQueue,Msg);
  2017.             }
  2018.             else
  2019.             {
  2020.                 ClearCursor();
  2021.  
  2022.                 (*ConProcessData)(String,Size);
  2023.  
  2024.                 DrawCursor();
  2025.             }
  2026.         }
  2027.         else
  2028.         {
  2029.             ClearCursor();
  2030.  
  2031.             (*ConProcessData)(String,Size);
  2032.  
  2033.             DrawCursor();
  2034.         }
  2035.     }
  2036. }
  2037.  
  2038.     /* ConWrites(STRPTR String,...):
  2039.      *
  2040.      *    Output a string to the console.
  2041.      */
  2042.  
  2043. VOID __stdargs
  2044. ConWrites(STRPTR String,...)
  2045. {
  2046.     va_list    VarArgs;
  2047.  
  2048.     if(Marking)
  2049.         DropMarker();
  2050.  
  2051.     va_start(VarArgs,String);
  2052.     VSPrintf(SharedBuffer,String,VarArgs);
  2053.     va_end(VarArgs);
  2054.  
  2055.     ConProcess(SharedBuffer,strlen(SharedBuffer));
  2056. }
  2057.  
  2058.     /* FlowInit():
  2059.      *
  2060.      *    Set up the data flow parser. The parser scans the serial
  2061.      *    output data for more or less interesting modem output
  2062.      *    (carrier lost, connect, etc.).
  2063.      */
  2064.  
  2065. VOID __regargs
  2066. FlowInit(BYTE FullReset)
  2067. {
  2068.     WORD i;
  2069.  
  2070.     for(i = 0 ; i < SCAN_COUNT ; i++)
  2071.         AttentionBuffers[i][0] = 0;
  2072.  
  2073.         /* Set up `NO CARRIER' message. */
  2074.  
  2075.     if(Config -> ModemConfig -> NoCarrier[0])
  2076.         SPrintf(AttentionBuffers[SCAN_NOCARRIER],"%s\r",Config -> ModemConfig -> NoCarrier);
  2077.  
  2078.         /* Set up ZRQINIT message. */
  2079.  
  2080. //    strcpy(AttentionBuffers[SCAN_ZMODEM],"*\030B01");
  2081.  
  2082.         /* Set up `CONNECT' message. */
  2083.  
  2084.     strcpy(AttentionBuffers[SCAN_CONNECT],Config -> ModemConfig -> Connect);
  2085.  
  2086.         /* Set up `VOICE' message. */
  2087.  
  2088.     if(Config -> ModemConfig -> Voice[0])
  2089.         SPrintf(AttentionBuffers[SCAN_VOICE],"%s\r",Config -> ModemConfig -> Voice);
  2090.  
  2091.         /* Set up `RING' message. */
  2092.  
  2093.     if(Config -> ModemConfig -> Ring[0])
  2094.         SPrintf(AttentionBuffers[SCAN_RING],"%s\r",Config -> ModemConfig -> Ring);
  2095.  
  2096.         /* Set up `BUSY' message. */
  2097.  
  2098.     if(Config -> ModemConfig -> Busy[0])
  2099.         SPrintf(AttentionBuffers[SCAN_BUSY],"%s\r",Config -> ModemConfig -> Busy);
  2100.  
  2101.         /* Set up `NO DIALTONE' message. */
  2102.  
  2103.     if(Config -> ModemConfig -> NoDialTone[0])
  2104.         SPrintf(AttentionBuffers[SCAN_NODIALTONE],"%s\r",Config -> ModemConfig -> NoDialTone);
  2105.  
  2106.         /* Set up `OK' message. */
  2107.  
  2108.     if(Config -> ModemConfig -> Ok[0])
  2109.         SPrintf(AttentionBuffers[SCAN_OK],"%s\r",Config -> ModemConfig -> Ok);
  2110.  
  2111.         /* Set up `ERROR' message. */
  2112.  
  2113.     if(Config -> ModemConfig -> Error[0])
  2114.         SPrintf(AttentionBuffers[SCAN_ERROR],"%s\r",Config -> ModemConfig -> Error);
  2115.  
  2116.         /* Reset match counter. */
  2117.  
  2118.     FlowCount = 0;
  2119.  
  2120.         /* Reset indices. */
  2121.  
  2122.     memset(AttentionCount,0,sizeof(AttentionCount));
  2123.  
  2124.         /* Determine lengths. */
  2125.  
  2126.     for(i = 0 ; i < SCAN_COUNT ; i++)
  2127.         AttentionLength[i] = strlen(AttentionBuffers[i]);
  2128.  
  2129.     for(i = SCAN_SIGDEFAULTUPLOAD ; i <= SCAN_SIGBINARYDOWNLOAD ; i++)
  2130.     {
  2131.         if(AttentionLength[i] = Config -> TransferConfig -> Signatures[TRANSFERSIG_DEFAULTUPLOAD + i - SCAN_SIGDEFAULTUPLOAD] . Length)
  2132.             memcpy(AttentionBuffers[i],Config -> TransferConfig -> Signatures[TRANSFERSIG_DEFAULTUPLOAD + i - SCAN_SIGDEFAULTUPLOAD] . Signature,Config -> TransferConfig -> Signatures[TRANSFERSIG_DEFAULTUPLOAD + i - SCAN_SIGDEFAULTUPLOAD] . Length);
  2133.     }
  2134.  
  2135.     if(Config -> TransferConfig -> ASCIIUploadType != XFER_XPR && Config -> TransferConfig -> ASCIIUploadType != XFER_EXTERNALPROGRAM)
  2136.         AttentionLength[SCAN_SIGASCIIUPLOAD] = 0;
  2137.  
  2138.     if(Config -> TransferConfig -> ASCIIDownloadType != XFER_XPR && Config -> TransferConfig -> ASCIIUploadType != XFER_EXTERNALPROGRAM)
  2139.         AttentionLength[SCAN_SIGASCIIDOWNLOAD] = 0;
  2140.  
  2141.     if(Config -> TransferConfig -> TextUploadType != XFER_XPR && Config -> TransferConfig -> TextUploadType != XFER_EXTERNALPROGRAM)
  2142.         AttentionLength[SCAN_SIGTEXTUPLOAD] = 0;
  2143.  
  2144.     if(Config -> TransferConfig -> TextDownloadType != XFER_XPR && Config -> TransferConfig -> TextUploadType != XFER_EXTERNALPROGRAM)
  2145.         AttentionLength[SCAN_SIGTEXTDOWNLOAD] = 0;
  2146.  
  2147.     if(Config -> TransferConfig -> BinaryUploadType != XFER_XPR && Config -> TransferConfig -> BinaryUploadType != XFER_EXTERNALPROGRAM)
  2148.         AttentionLength[SCAN_SIGBINARYUPLOAD] = 0;
  2149.  
  2150.     if(Config -> TransferConfig -> BinaryDownloadType != XFER_XPR && Config -> TransferConfig -> BinaryUploadType != XFER_EXTERNALPROGRAM)
  2151.         AttentionLength[SCAN_SIGBINARYDOWNLOAD] = 0;
  2152.  
  2153.     if(FullReset)
  2154.     {
  2155.             /* No, we are not yet looking for a baud rate. */
  2156.  
  2157.         BaudPending = FALSE;
  2158.  
  2159.             /* Reset the flags. */
  2160.  
  2161.         memset(&FlowInfo,FALSE,sizeof(struct FlowInfo));
  2162.     }
  2163.  
  2164.         /* Full data check is a lot slower than looking for
  2165.          * just a single sequence (such as the `CONNECT'
  2166.          * below). This mode is reserved for the dial panel.
  2167.          */
  2168.  
  2169.     ScanStart    = 0;
  2170.     ScanEnd        = SCAN_COUNT - 1;
  2171.     UseFlow        = TRUE;
  2172. }
  2173.  
  2174.     /* GfxText(struct RastPort *RPort,STRPTR Buffer,LONG Length):
  2175.      *
  2176.      *    Text output, if necessary switching from gfx font
  2177.      *    to current default font.
  2178.      */
  2179.  
  2180. VOID __regargs
  2181. GfxText(struct RastPort *RPort,STRPTR Buffer,LONG Length)
  2182. {
  2183.     BYTE TextMode;
  2184.     LONG SameMode;
  2185.  
  2186.         /* Determine current text rendering mode. */
  2187.  
  2188.     if(GfxTable[Buffer[0]] == MODE_GFX)
  2189.         TextMode = MODE_GFX;
  2190.     else
  2191.     {
  2192.         TextMode = MODE_STANDARD;
  2193.  
  2194.         SetFont(RPort,TextFont);
  2195.     }
  2196.  
  2197.         /* Reset number of characters in common mode. */
  2198.  
  2199.     SameMode = 0;
  2200.  
  2201.         /* Scan until all input is processed. */
  2202.  
  2203.     FOREVER
  2204.     {
  2205.             /* Scan for characters in the current mode. */
  2206.  
  2207.         while(GfxTable[Buffer[SameMode]] == TextMode && SameMode < Length)
  2208.             SameMode++;
  2209.  
  2210.             /* Output the text found. */
  2211.  
  2212.         Text(RPort,Buffer,SameMode);
  2213.  
  2214.             /* Decrement number of remaining bytes. */
  2215.  
  2216.         Length -= SameMode;
  2217.  
  2218.             /* Anything left? */
  2219.  
  2220.         if(Length)
  2221.         {
  2222.                 /* Skip to next character. */
  2223.  
  2224.             Buffer        += SameMode;
  2225.             SameMode     = 0;
  2226.  
  2227.                 /* Change text output mode. */
  2228.  
  2229.             if(TextMode == MODE_GFX)
  2230.             {
  2231.                 SetFont(RPort,TextFont);
  2232.  
  2233.                 TextMode = MODE_STANDARD;
  2234.             }
  2235.             else
  2236.             {
  2237.                 SetFont(RPort,GFX);
  2238.  
  2239.                 TextMode = MODE_GFX;
  2240.             }
  2241.         }
  2242.         else
  2243.             break;
  2244.     }
  2245.  
  2246.         /* Reset font type. */
  2247.  
  2248.     if(TextMode == MODE_STANDARD)
  2249.         SetFont(RPort,GFX);
  2250. }
  2251.  
  2252.     /* ConvertKey():
  2253.      *
  2254.      *    The actual key conversion routine.
  2255.      */
  2256.  
  2257. STATIC LONG __inline
  2258. ConvertKey(ULONG Qualifier,UWORD Code,ULONG Prev,STRPTR Buffer,LONG Len)
  2259. {
  2260.     LONG Actual;
  2261.  
  2262.         /* Fill in the defaults. */
  2263.  
  2264.     FakeInputEvent -> ie_Code        = Code;
  2265.     FakeInputEvent -> ie_Qualifier        = Qualifier;
  2266.     FakeInputEvent -> ie_position . ie_addr    = (APTR)Prev;
  2267.  
  2268.         /* Clear the buffer (sortof). */
  2269.  
  2270.     Buffer[0] = 0;
  2271.  
  2272.         /* Convert the codes. */
  2273.  
  2274.     if((Actual = RawKeyConvert(FakeInputEvent,Buffer,Len,KeyMap)) > 0)
  2275.         return(Actual);
  2276.     else
  2277.         return(0);
  2278. }
  2279.  
  2280.     /* ConvertTheKey(STRPTR Buffer,LONG *Len,UWORD Code,UWORD Qualifier,ULONG Prev):
  2281.      *
  2282.      *    Much more simplified raw key conversion routine.
  2283.      */
  2284.  
  2285. UBYTE __regargs
  2286. ConvertTheKey(STRPTR Buffer,LONG *Len,UWORD Code,UWORD Qualifier,ULONG Prev)
  2287. {
  2288.     if(Buffer)
  2289.         Buffer[0] = 0;
  2290.  
  2291.     if(Len)
  2292.         *Len = 0;
  2293.  
  2294.         /* Key was pressed, not released. */
  2295.  
  2296.     if(!(Code & IECODE_UP_PREFIX))
  2297.     {
  2298.             /* These are the sequences mapped to special
  2299.              * control keys (cursor keys, function keys,
  2300.              * the help key).
  2301.              */
  2302.  
  2303.         STATIC struct { STRPTR RawCode; UBYTE Result; } ConversionTable[15] =
  2304.         {
  2305.             (STRPTR)"A",    CUP,
  2306.             (STRPTR)"B",    CDN,
  2307.             (STRPTR)"C",    CFW,
  2308.             (STRPTR)"D",    CBK,
  2309.  
  2310.             (STRPTR)"?~",    HLP,
  2311.  
  2312.             (STRPTR)"0~",    FN1,
  2313.             (STRPTR)"1~",    FN2,
  2314.             (STRPTR)"2~",    FN3,
  2315.             (STRPTR)"3~",    FN4,
  2316.             (STRPTR)"4~",    FN5,
  2317.             (STRPTR)"5~",    FN6,
  2318.             (STRPTR)"6~",    FN7,
  2319.             (STRPTR)"7~",    FN8,
  2320.             (STRPTR)"8~",    FN9,
  2321.             (STRPTR)"9~",    F10
  2322.         };
  2323.  
  2324.         STATIC UBYTE SeqLens[15] = { 1,1,1,1,2,2,2,2,2,2,2,2,2,2,2 };
  2325.  
  2326.         UBYTE    ConvertBuffer[257];
  2327.         LONG    Actual;
  2328.  
  2329.             /* If it's a function or cursor key, clear the qualifier. */
  2330.  
  2331.         if(Code >= CURSOR_UP_CODE && Code <= F10_CODE)
  2332.             Qualifier = NULL;
  2333.         else
  2334.         {
  2335.                 /* Does it have a numeric keypad qualifier set? */
  2336.  
  2337.             if((Qualifier & (IEQUALIFIER_NUMERICPAD | IEQUALIFIER_CONTROL)) == (IEQUALIFIER_NUMERICPAD | IEQUALIFIER_CONTROL))
  2338.             {
  2339.                 STRPTR String = NULL;
  2340.  
  2341.                     /* Look at the vanilla result. */
  2342.  
  2343.                 if(ConvertKey(Qualifier & ~(IEQUALIFIER_CONTROL | IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT | IEQUALIFIER_LALT | IEQUALIFIER_RALT),Code,Prev,ConvertBuffer,1))
  2344.                 {
  2345.                         /* Take a look at the results. */
  2346.  
  2347.                     switch(ConvertBuffer[0])
  2348.                     {
  2349.                         case '(':
  2350.                         case '[':
  2351.                         case '{':
  2352.  
  2353.                             String = "\033OP";
  2354.                             break;
  2355.  
  2356.                         case ')':
  2357.                         case ']':
  2358.                         case '}':
  2359.  
  2360.                             String = "\033OQ";
  2361.                             break;
  2362.  
  2363.                         case '/':
  2364.  
  2365.                             String = "\033OR";
  2366.                             break;
  2367.  
  2368.                         case '*':
  2369.  
  2370.                             String = "\033OS";
  2371.                             break;
  2372.  
  2373.                         default:
  2374.  
  2375.                             String = NULL;
  2376.                             break;
  2377.                     }
  2378.                 }
  2379.  
  2380.                 if(!String)
  2381.                 {
  2382.                     switch(Code)
  2383.                     {
  2384.                         case 0x5A:
  2385.  
  2386.                             String = "\033OP";
  2387.                             break;
  2388.  
  2389.                         case 0x5B:
  2390.  
  2391.                             String = "\033OQ";
  2392.                             break;
  2393.  
  2394.                         case 0x5C:
  2395.  
  2396.                             String = "\033OR";
  2397.                             break;
  2398.  
  2399.                         case 0x5D:
  2400.  
  2401.                             String = "\033OS";
  2402.                             break;
  2403.                     }
  2404.                 }
  2405.  
  2406.                     /* Return the PFx key code. */
  2407.  
  2408.                 if(String)
  2409.                 {
  2410.                     if(Buffer)
  2411.                         memcpy(Buffer,String,3);
  2412.  
  2413.                     if(Len)
  2414.                         *Len = 3;
  2415.  
  2416.                     return('\033');
  2417.                 }
  2418.             }
  2419.  
  2420.                 /* Does it have a shift qualifier set? */
  2421.  
  2422.             if(Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
  2423.             {
  2424.                     /* Do the conversion... */
  2425.  
  2426.                 if(ConvertKey(Qualifier & ~(IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT),Code,Prev,ConvertBuffer,1))
  2427.                 {
  2428.                         /* Did it produce a tab key? If so, transfer
  2429.                          * Esc tab instead.
  2430.                          */
  2431.  
  2432.                     if(ConvertBuffer[0] == '\t')
  2433.                     {
  2434.                         if(Len)
  2435.                             *Len = 2;
  2436.  
  2437.                         if(Buffer)
  2438.                             memcpy(Buffer,"\033\t",2);
  2439.  
  2440.                         return('\033');
  2441.                     }
  2442.                 }
  2443.             }
  2444.  
  2445.                 /* Does it have the control qualifier set? */
  2446.  
  2447.             if(Qualifier & IEQUALIFIER_CONTROL)
  2448.             {
  2449.                     /* Do the conversion... */
  2450.  
  2451.                 if(ConvertKey(Qualifier & ~IEQUALIFIER_CONTROL,Code,Prev,ConvertBuffer,1))
  2452.                 {
  2453.                         /* Did it produce a space or an `at' sign? */
  2454.  
  2455.                     switch(ConvertBuffer[0])
  2456.                     {
  2457.                             /* NUL */
  2458.  
  2459.                         case ' ':
  2460.                         case '@':
  2461.                         case '2':
  2462.  
  2463.                             if(Len)
  2464.                                 *Len = 1;
  2465.  
  2466.                             if(Buffer)
  2467.                                 Buffer[0] = 0;
  2468.  
  2469.                             return(0);
  2470.  
  2471.                             /* Escape */
  2472.  
  2473.                         case '3':
  2474.                         case '[':
  2475.  
  2476.                             if(Len)
  2477.                                 *Len = 1;
  2478.  
  2479.                             if(Buffer)
  2480.                                 Buffer[0] = 0x1B;
  2481.  
  2482.                             return(0x1B);
  2483.  
  2484.                             /* FS */
  2485.  
  2486.                         case '4':
  2487.                         case '/':
  2488.  
  2489.                             if(Len)
  2490.                                 *Len = 1;
  2491.  
  2492.                             if(Buffer)
  2493.                                 Buffer[0] = 0x1C;
  2494.  
  2495.                             return(0x1C);
  2496.  
  2497.                             /* GS */
  2498.  
  2499.                         case '5':
  2500.                         case ']':
  2501.  
  2502.                             if(Len)
  2503.                                 *Len = 1;
  2504.  
  2505.                             if(Buffer)
  2506.                                 Buffer[0] = 0x1D;
  2507.  
  2508.                             return(0x1D);
  2509.  
  2510.                             /* RS */
  2511.  
  2512.                         case '6':
  2513.                         case '~':
  2514.  
  2515.                             if(Len)
  2516.                                 *Len = 1;
  2517.  
  2518.                             if(Buffer)
  2519.                                 Buffer[0] = 0x1E;
  2520.  
  2521.                             return(0x1E);
  2522.  
  2523.  
  2524.                             /* US */
  2525.  
  2526.                         case '7':
  2527.                         case '?':
  2528.  
  2529.                             if(Len)
  2530.                                 *Len = 1;
  2531.  
  2532.                             if(Buffer)
  2533.                                 Buffer[0] = 0x1F;
  2534.  
  2535.                             return(0x1F);
  2536.                     }
  2537.                 }
  2538.             }
  2539.         }
  2540.  
  2541.             /* Do the final conversion... */
  2542.  
  2543.         if(Actual = ConvertKey(Qualifier,Code,Prev,ConvertBuffer,256))
  2544.         {
  2545.                 /* Are we to swap the backspace and
  2546.                  * delete keys?
  2547.                  */
  2548.  
  2549.             if(Config -> EmulationConfig -> SwapBSDelete)
  2550.             {
  2551.                 register WORD i;
  2552.  
  2553.                 for(i = 0 ; i < Actual ; i++)
  2554.                 {
  2555.                     if(ConvertBuffer[i] == BKS)
  2556.                         ConvertBuffer[i] = DEL;
  2557.                     else
  2558.                     {
  2559.                         if(ConvertBuffer[i] == DEL)
  2560.                             ConvertBuffer[i] = BKS;
  2561.                     }
  2562.                 }
  2563.             }
  2564.  
  2565.                 /* Translated sequence starts
  2566.                  * with a CSI, let's have a look
  2567.                  * at the associated control
  2568.                  * key.
  2569.                  */
  2570.  
  2571.             if(ConvertBuffer[0] == CSI)
  2572.             {
  2573.                 register WORD i;
  2574.  
  2575.                 for(i = 0 ; i < sizeof(SeqLens) ; i++)
  2576.                 {
  2577.                         /* Does it match? */
  2578.  
  2579.                     if(!memcmp(&ConvertBuffer[1],ConversionTable[i] . RawCode,SeqLens[i]))
  2580.                     {
  2581.                             /* Store the length. */
  2582.  
  2583.                         if(Len)
  2584.                             *Len = 1;
  2585.  
  2586.                             /* Store the result. */
  2587.  
  2588.                         if(Buffer)
  2589.                         {
  2590.                             Buffer[0] = ConversionTable[i] . Result;
  2591.                             Buffer[1] = 0;
  2592.                         }
  2593.  
  2594.                         return(ConversionTable[i] . Result);
  2595.                     }
  2596.                 }
  2597.             }
  2598.  
  2599.                 /* Store the number of characters converted. */
  2600.  
  2601.             if(Len)
  2602.                 *Len = Actual;
  2603.  
  2604.                 /* Store the converted characters. */
  2605.  
  2606.             if(Buffer)
  2607.                 memcpy(Buffer,ConvertBuffer,Actual);
  2608.  
  2609.             return(ConvertBuffer[0]);
  2610.         }
  2611.     }
  2612.  
  2613.     return(0);
  2614. }
  2615.  
  2616.     /* KeyConvert(struct IntuiMessage *Massage,STRPTR Buffer):
  2617.      *
  2618.      *    Convert a raw key information according to the
  2619.      *    current keymap settings.
  2620.      */
  2621.  
  2622. UBYTE __regargs
  2623. KeyConvert(struct IntuiMessage *Massage,STRPTR Buffer,LONG *Len)
  2624. {
  2625.         /* Is this really a keyboard event? */
  2626.  
  2627.     if(Massage -> Class == IDCMP_RAWKEY)
  2628.         return(ConvertTheKey(Buffer,Len,Massage -> Code,Massage -> Qualifier,*(ULONG *)Massage -> IAddress));
  2629.     else
  2630.     {
  2631.         if(Buffer)
  2632.             Buffer[0] = 0;
  2633.  
  2634.         if(Len)
  2635.             *Len = 0;
  2636.  
  2637.         return(0);
  2638.     }
  2639. }
  2640.  
  2641.     /* DoBackspace():
  2642.      *
  2643.      *    Special function: perform backspace.
  2644.      */
  2645.  
  2646. BYTE
  2647. DoBackspace()
  2648. {
  2649.     if(CursorX)
  2650.     {
  2651.         WORD DeltaX,MinX;
  2652.  
  2653.         CursorX--;
  2654.  
  2655.             // What backspace mode are we in?
  2656.  
  2657.         switch(Config -> EmulationConfig -> DestructiveBackspace)
  2658.         {
  2659.                 // Do nothing
  2660.  
  2661.             case 0:
  2662.  
  2663.                 RepositionCursor();
  2664.                 break;
  2665.  
  2666.                 // Shift the line to the left
  2667.  
  2668.             case 2:
  2669.  
  2670.                 BackupRender();
  2671.  
  2672.                 RasterEraseCharacters(1);
  2673.  
  2674.                 if(FontScalingRequired)
  2675.                 {
  2676.                     if(CurrentCharWidth == SCALE_NORMAL)
  2677.                     {
  2678.                         DeltaX    = TextFontWidth * 2;
  2679.                         MinX    = MUL_X(CursorX) * 2;
  2680.                     }
  2681.                     else
  2682.                     {
  2683.                         DeltaX    = TextFontWidth / 2;
  2684.                         MinX    = MUL_X(CursorX) / 2;
  2685.                     }
  2686.                 }
  2687.                 else
  2688.                 {
  2689.                     DeltaX    = TextFontWidth;
  2690.                     MinX    = MUL_X(CursorX);
  2691.                 }
  2692.  
  2693.                 ScrollLineEraseCharacters(1);
  2694.  
  2695.                 ScrollLineRaster(RPort,DeltaX,0,MinX,MUL_Y(CursorY),LastPixel,MUL_Y(CursorY + 1) - 1,FALSE);
  2696.  
  2697.                 BackupRender();
  2698.  
  2699.                 RepositionCursor();
  2700.  
  2701.                 break;
  2702.  
  2703.                 // Clear the character below the cursor
  2704.  
  2705.             default:
  2706.  
  2707.                 RepositionCursor();
  2708.  
  2709.                 ObtainSemaphore(RasterSemaphore);
  2710.  
  2711.                 Raster[CursorY * RasterWidth + CursorX] = ' ';
  2712.  
  2713.                 ReleaseSemaphore(RasterSemaphore);
  2714.  
  2715.                 BackupRender();
  2716.  
  2717.                 if(FontScalingRequired)
  2718.                     PrintScaled(" ",1,CurrentFontScale);
  2719.                 else
  2720.                     Text(RPort," ",1);
  2721.  
  2722.                 BackupRender();
  2723.  
  2724.                 break;
  2725.         }
  2726.     }
  2727.  
  2728.     return(FALSE);
  2729. }
  2730.  
  2731.     /* DoBeep():
  2732.      *
  2733.      *    The real interface to the beep routine.
  2734.      */
  2735.  
  2736. BYTE
  2737. DoBeep()
  2738. {
  2739.     BellSignal();
  2740.  
  2741.     return(FALSE);
  2742. }
  2743.  
  2744.     /* DoxON():
  2745.      *
  2746.      *    Perform XON (stop data flow).
  2747.      */
  2748.  
  2749. BYTE
  2750. DoxON()
  2751. {
  2752.         // Commented out, `term' now handles xON locally only
  2753.  
  2754. //    if(Config -> SerialConfig -> xONxOFF)
  2755. //        Status = STATUS_HOLDING;
  2756.  
  2757.     return(FALSE);
  2758. }
  2759.  
  2760.     /* DoLF():
  2761.      *
  2762.      *    Special function: perform line feed.
  2763.      */
  2764.  
  2765. BYTE
  2766. DoLF()
  2767. {
  2768.         // This takes care of regular jump scrolling
  2769.  
  2770.     if(CursorY == Bottom && Bottom > 0 && Config -> EmulationConfig -> MaxJump > 1)
  2771.     {
  2772.         WORD Scroll,TotalLines,OldBack = BackgroundPen;
  2773.  
  2774.         Scroll = Config -> EmulationConfig -> MaxJump;
  2775.  
  2776.             // How tall is the current scroll region?
  2777.  
  2778.         TotalLines = Bottom - Top + 1;
  2779.  
  2780.             // Don't scroll more than the entire screenful
  2781.  
  2782.         if(Scroll > TotalLines)
  2783.             Scroll = TotalLines;
  2784.  
  2785.         if(OldBack)
  2786.         {
  2787.             BackgroundPen = 0;
  2788.  
  2789.             UpdatePens();
  2790.         }
  2791.  
  2792.             // Scroll the region...
  2793.  
  2794.         ScrollRegion(Scroll);
  2795.  
  2796.             // Reposition the cursor
  2797.  
  2798.         if(CursorY > Scroll)
  2799.             CursorY -= Scroll;
  2800.         else
  2801.             CursorY = 0;
  2802.  
  2803.         if(OldBack)
  2804.         {
  2805.             BackgroundPen = OldBack;
  2806.  
  2807.             UpdatePens();
  2808.         }
  2809.     }
  2810.  
  2811.     DownLine();
  2812.  
  2813.     RepositionCursor();
  2814.  
  2815.     return(FALSE);
  2816. }
  2817.  
  2818.     /* DoShiftIn():
  2819.      *
  2820.      *    Special function: Shift into graphics mode
  2821.      */
  2822.  
  2823. BYTE
  2824. DoShiftIn()
  2825. {
  2826.     if(CharMode[1] == TABLE_GFX && GFX)
  2827.         CurrentFont = GFX;
  2828.  
  2829.     if(CharMode[1] == TABLE_ASCII)
  2830.         CurrentFont = TextFont;
  2831.  
  2832.     SetFont(RPort,CurrentFont);
  2833.  
  2834.     ConOutputUpdate();
  2835.  
  2836.     Charset = 1;
  2837.  
  2838.     return(FALSE);
  2839. }
  2840.  
  2841.     /* DoShiftOut():
  2842.      *
  2843.      *    Special function: Shift out of graphics mode
  2844.      */
  2845.  
  2846. BYTE
  2847. DoShiftOut()
  2848. {
  2849.     if(CharMode[0] == TABLE_GFX && GFX)
  2850.         CurrentFont = GFX;
  2851.  
  2852.     if(CharMode[0] == TABLE_ASCII)
  2853.         CurrentFont = TextFont;
  2854.  
  2855.     SetFont(RPort,CurrentFont);
  2856.  
  2857.     ConOutputUpdate();
  2858.  
  2859.     Charset = 0;
  2860.  
  2861.     return(FALSE);
  2862. }
  2863.  
  2864.     /* DoCR_LF():
  2865.      *
  2866.      *    Special function: perform carriage return and line feed.
  2867.      */
  2868.  
  2869. BYTE
  2870. DoCR_LF()
  2871. {
  2872.     CursorX = 0;
  2873.  
  2874.     DownLine();
  2875.  
  2876.     RepositionCursor();
  2877.  
  2878.     return(FALSE);
  2879. }
  2880.  
  2881.     /* DoFF():
  2882.      *
  2883.      *    Special function: perform form feed.
  2884.      */
  2885.  
  2886. BYTE
  2887. DoFF()
  2888. {
  2889.     if(Config -> EmulationConfig -> NewLineMode)
  2890.     {
  2891.         CursorX = 0;
  2892.  
  2893.         DoCR_LF();
  2894.     }
  2895.     else
  2896.     {
  2897.         EraseScreen("2");
  2898.  
  2899.         CursorX = CursorY = 0;
  2900.  
  2901.         RepositionCursor();
  2902.  
  2903.         ConFontScaleUpdate();
  2904.     }
  2905.  
  2906.     return(FALSE);
  2907. }
  2908.  
  2909.     /* DoLF_FF_VT():
  2910.      *
  2911.      *    Special function: handle line feed, form feed and vertical
  2912.      *    tab.
  2913.      */
  2914.  
  2915. BYTE
  2916. DoLF_FF_VT()
  2917. {
  2918.     if(Config -> EmulationConfig -> NewLineMode)
  2919.         DoCR_LF();
  2920.     else
  2921.         DoLF();
  2922.  
  2923.     return(FALSE);
  2924. }
  2925.  
  2926.     /* DoCR():
  2927.      *
  2928.      *    Special function: handle carriage return.
  2929.      */
  2930.  
  2931. BYTE
  2932. DoCR()
  2933. {
  2934.     if(Config -> EmulationConfig -> NewLineMode)
  2935.         DoCR_LF();
  2936.     else
  2937.     {
  2938.         CursorX = 0;
  2939.  
  2940.         RepositionCursor();
  2941.     }
  2942.  
  2943.     return(FALSE);
  2944. }
  2945.  
  2946.     /* DoTab():
  2947.      *
  2948.      *    Special function: handle tab, move cursor to next
  2949.      *    tab stop.
  2950.      */
  2951.  
  2952. BYTE
  2953. DoTab()
  2954. {
  2955.     WORD Column;
  2956.  
  2957.     if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
  2958.         Column = LastColumn;
  2959.     else
  2960.         Column = ((LastColumn + 1) / 2) - 1;
  2961.  
  2962.     if(Config -> EmulationConfig -> LineWrap)
  2963.     {
  2964.         if(CursorX >= LastColumn)
  2965.         {
  2966.             CursorX = 0;
  2967.  
  2968.             DownLine();
  2969.         }
  2970.         else
  2971.         {
  2972.             while(CursorX < Column)
  2973.             {
  2974.                 CursorX++;
  2975.  
  2976.                 if(TabStops[CursorX])
  2977.                     break;
  2978.             }
  2979.         }
  2980.     }
  2981.     else
  2982.     {
  2983.         while(CursorX < Column)
  2984.         {
  2985.             CursorX++;
  2986.  
  2987.             if(TabStops[CursorX])
  2988.                 break;
  2989.         }
  2990.     }
  2991.  
  2992.     RepositionCursor();
  2993.  
  2994.     return(FALSE);
  2995. }
  2996.  
  2997.     /* DoEnq():
  2998.      *
  2999.      *    Special function: send answerback message.
  3000.      */
  3001.  
  3002. BYTE
  3003. DoEnq()
  3004. {
  3005.     if(Config -> EmulationConfig -> AnswerBack[0])
  3006.         SerialCommand(Config -> EmulationConfig -> AnswerBack);
  3007.  
  3008.     return(FALSE);
  3009. }
  3010.  
  3011.     /* DoEsc():
  3012.      *
  3013.      *    Start new control sequence.
  3014.      */
  3015.  
  3016. BYTE
  3017. DoEsc()
  3018. {
  3019.     if(Config -> TerminalConfig -> EmulationMode == EMULATION_TTY)
  3020.         (* ConDump)("^",1);
  3021.  
  3022.     return(TRUE);
  3023. }
  3024.  
  3025.     /* DoCsi():
  3026.      *
  3027.      *    Start new control sequence.
  3028.      */
  3029.  
  3030. BYTE
  3031. DoCsi()
  3032. {
  3033.     if(Config -> TerminalConfig -> EmulationMode == EMULATION_TTY)
  3034.         (* ConDump)("^[",2);
  3035.  
  3036.     ParseCode('[');
  3037.  
  3038.     return(TRUE);
  3039. }
  3040.  
  3041.     /* DoNewEsc(UBYTE Char):
  3042.      *
  3043.      *    Start new control sequence.
  3044.      */
  3045.  
  3046. BYTE
  3047. DoNewEsc(UBYTE Char)
  3048. {
  3049.     if(Config -> TerminalConfig -> EmulationMode == EMULATION_TTY)
  3050.         (* ConDump)("^",1);
  3051.  
  3052.     DoCancel();
  3053.  
  3054.     InSequence = TRUE;
  3055.  
  3056.     return(TRUE);
  3057. }
  3058.  
  3059.     /* DoNewCsi(UBYTE Char):
  3060.      *
  3061.      *    Start new control sequence.
  3062.      */
  3063.  
  3064. BYTE
  3065. DoNewCsi(UBYTE Char)
  3066. {
  3067.     if(Config -> TerminalConfig -> EmulationMode == EMULATION_TTY)
  3068.         (* ConDump)("^[",2);
  3069.  
  3070.     DoCancel();
  3071.  
  3072.     InSequence = TRUE;
  3073.  
  3074.     return(ParseCode('['));
  3075. }
  3076.  
  3077. STATIC STRPTR    CR_Translation,
  3078.         LF_Translation;
  3079. STATIC WORD    CR_Trans_Len,
  3080.         LF_Trans_Len;
  3081.  
  3082. STATIC LONG __regargs
  3083. Translate_CR_LF_1(register STRPTR Data,register LONG Size)
  3084. {
  3085.     register STRPTR    String    = Data;
  3086.     register LONG    Count    = 0;
  3087.     register UBYTE    c;
  3088.  
  3089.     while(Size--)
  3090.     {
  3091.         switch(c = *Data++)
  3092.         {
  3093.             case '\r':
  3094.  
  3095.                 if(CR_Trans_Len)
  3096.                 {
  3097.                     *String++ = *CR_Translation;
  3098.  
  3099.                     Count++;
  3100.                 }
  3101.  
  3102.                 break;
  3103.  
  3104.             case '\n':
  3105.  
  3106.                 if(LF_Trans_Len)
  3107.                 {
  3108.                     *String++ = *LF_Translation;
  3109.  
  3110.                     Count++;
  3111.                 }
  3112.  
  3113.                 break;
  3114.  
  3115.             default:
  3116.  
  3117.                 *String++ = c;
  3118.  
  3119.                 Count++;
  3120.  
  3121.                 break;
  3122.         }
  3123.     }
  3124.  
  3125.     return(Count);
  3126. }
  3127.  
  3128. STATIC LONG __regargs
  3129. Translate_CR_LF_2x2(register STRPTR Data,register LONG Size)
  3130. {
  3131.     register STRPTR    String    = Data;
  3132.     register LONG    Count    = 0;
  3133.     register UBYTE    c;
  3134.  
  3135.     /* ALWAYS */
  3136.     {
  3137.         register BOOL GotIt = FALSE;
  3138.         register LONG i;
  3139.  
  3140.         for(i = 0 ; i < Size ; i++)
  3141.         {
  3142.             if(String[i] == '\r' || String[i] == '\n')
  3143.             {
  3144.                 GotIt = TRUE;
  3145.  
  3146.                 break;
  3147.             }
  3148.         }
  3149.  
  3150.         if(GotIt)
  3151.         {
  3152.             CopyMem(Data,StripBuffer,Size);
  3153.  
  3154.             String    = Data;
  3155.             Data    = StripBuffer;
  3156.         }
  3157.         else
  3158.             return(Size);
  3159.     }
  3160.  
  3161.     while(Size--)
  3162.     {
  3163.         switch(c = *Data++)
  3164.         {
  3165.             case '\r':
  3166.  
  3167.                 if(CR_Trans_Len)
  3168.                 {
  3169.                     register WORD i;
  3170.  
  3171.                     for(i = 0 ; i < CR_Trans_Len ; i++)
  3172.                     {
  3173.                         *String++ = CR_Translation[i];
  3174.  
  3175.                         Count++;
  3176.                     }
  3177.                 }
  3178.  
  3179.                 break;
  3180.  
  3181.             case '\n':
  3182.  
  3183.                 if(LF_Trans_Len)
  3184.                 {
  3185.                     register WORD i;
  3186.  
  3187.                     for(i = 0 ; i < LF_Trans_Len ; i++)
  3188.                     {
  3189.                         *String++ = LF_Translation[i];
  3190.  
  3191.                         Count++;
  3192.                     }
  3193.                 }
  3194.  
  3195.                 break;
  3196.  
  3197.             default:
  3198.  
  3199.                 *String++ = c;
  3200.  
  3201.                 Count++;
  3202.  
  3203.                 break;
  3204.         }
  3205.     }
  3206.  
  3207.     return(Count);
  3208. }
  3209.  
  3210. STATIC LONG __regargs
  3211. Translate_CR_LF_2LF(register STRPTR Data,register LONG Size)
  3212. {
  3213.     register STRPTR    String    = Data;
  3214.     register LONG    Count    = 0;
  3215.     register UBYTE    c;
  3216.  
  3217.     /* ALWAYS */
  3218.     {
  3219.         register BOOL GotIt = FALSE;
  3220.         register LONG i;
  3221.  
  3222.         for(i = 0 ; i < Size ; i++)
  3223.         {
  3224.             if(String[i] == '\n')
  3225.             {
  3226.                 GotIt = TRUE;
  3227.  
  3228.                 break;
  3229.             }
  3230.         }
  3231.  
  3232.         if(GotIt)
  3233.         {
  3234.             CopyMem(Data,StripBuffer,Size);
  3235.  
  3236.             String    = Data;
  3237.             Data    = StripBuffer;
  3238.         }
  3239.         else
  3240.             return(Size);
  3241.     }
  3242.  
  3243.     while(Size--)
  3244.     {
  3245.         switch(c = *Data++)
  3246.         {
  3247.             case '\r':
  3248.  
  3249.                 if(CR_Trans_Len)
  3250.                 {
  3251.                     register WORD i;
  3252.  
  3253.                     for(i = 0 ; i < CR_Trans_Len ; i++)
  3254.                     {
  3255.                         *String++ = CR_Translation[i];
  3256.  
  3257.                         Count++;
  3258.                     }
  3259.                 }
  3260.  
  3261.                 break;
  3262.  
  3263.             case '\n':
  3264.  
  3265.                 if(LF_Trans_Len)
  3266.                 {
  3267.                     register WORD i;
  3268.  
  3269.                     for(i = 0 ; i < LF_Trans_Len ; i++)
  3270.                     {
  3271.                         *String++ = LF_Translation[i];
  3272.  
  3273.                         Count++;
  3274.                     }
  3275.                 }
  3276.  
  3277.                 break;
  3278.  
  3279.             default:
  3280.  
  3281.                 *String++ = c;
  3282.  
  3283.                 Count++;
  3284.  
  3285.                 break;
  3286.         }
  3287.     }
  3288.  
  3289.     return(Count);
  3290. }
  3291.  
  3292. STATIC LONG __regargs
  3293. Translate_CR_LF_2CR(register STRPTR Data,register LONG Size)
  3294. {
  3295.     register STRPTR    String    = Data;
  3296.     register LONG    Count    = 0;
  3297.     register UBYTE    c;
  3298.  
  3299.     /* ALWAYS */
  3300.     {
  3301.         register BOOL GotIt = FALSE;
  3302.         register LONG i;
  3303.  
  3304.         for(i = 0 ; i < Size ; i++)
  3305.         {
  3306.             if(String[i] == '\r')
  3307.             {
  3308.                 GotIt = TRUE;
  3309.  
  3310.                 break;
  3311.             }
  3312.         }
  3313.  
  3314.         if(GotIt)
  3315.         {
  3316.             CopyMem(Data,StripBuffer,Size);
  3317.  
  3318.             String    = Data;
  3319.             Data    = StripBuffer;
  3320.         }
  3321.         else
  3322.             return(Size);
  3323.     }
  3324.  
  3325.     while(Size--)
  3326.     {
  3327.         switch(c = *Data++)
  3328.         {
  3329.             case '\r':
  3330.  
  3331.                 if(CR_Trans_Len)
  3332.                 {
  3333.                     register WORD i;
  3334.  
  3335.                     for(i = 0 ; i < CR_Trans_Len ; i++)
  3336.                     {
  3337.                         *String++ = CR_Translation[i];
  3338.  
  3339.                         Count++;
  3340.                     }
  3341.                 }
  3342.  
  3343.                 break;
  3344.  
  3345.             case '\n':
  3346.  
  3347.                 if(LF_Trans_Len)
  3348.                 {
  3349.                     register WORD i;
  3350.  
  3351.                     for(i = 0 ; i < LF_Trans_Len ; i++)
  3352.                     {
  3353.                         *String++ = LF_Translation[i];
  3354.  
  3355.                         Count++;
  3356.                     }
  3357.                 }
  3358.  
  3359.                 break;
  3360.  
  3361.             default:
  3362.  
  3363.                 *String++ = c;
  3364.  
  3365.                 Count++;
  3366.  
  3367.                 break;
  3368.         }
  3369.     }
  3370.  
  3371.     return(Count);
  3372. }
  3373.  
  3374. VOID
  3375. Update_CR_LF_Translation()
  3376. {
  3377.     Forbid();
  3378.  
  3379.     if(Config -> TerminalConfig -> ReceiveCR == EOL_CRLF || Config -> TerminalConfig -> ReceiveCR == EOL_LFCR || Config -> TerminalConfig -> ReceiveLF == EOL_LFCR || Config -> TerminalConfig -> ReceiveLF == EOL_CRLF)
  3380.         SerialBufferSize = Config -> SerialConfig -> SerialBufferSize / 2;
  3381.     else
  3382.         SerialBufferSize = Config -> SerialConfig -> SerialBufferSize;
  3383.  
  3384.     switch(Config -> TerminalConfig -> ReceiveCR)
  3385.     {
  3386.         case EOL_IGNORE:
  3387.  
  3388.             CR_Trans_Len = 0;
  3389.             break;
  3390.  
  3391.         case EOL_CR:
  3392.  
  3393.             CR_Trans_Len    = 1;
  3394.             CR_Translation    = "\r";
  3395.             break;
  3396.  
  3397.         case EOL_LF:
  3398.  
  3399.             CR_Trans_Len    = 1;
  3400.             CR_Translation    = "\n";
  3401.             break;
  3402.  
  3403.         case EOL_CRLF:
  3404.  
  3405.             CR_Trans_Len    = 2;
  3406.             CR_Translation    = "\r\n";
  3407.             break;
  3408.  
  3409.         case EOL_LFCR:
  3410.  
  3411.             CR_Trans_Len    = 2;
  3412.             CR_Translation    = "\n\r";
  3413.             break;
  3414.     }
  3415.  
  3416.     switch(Config -> TerminalConfig -> ReceiveLF)
  3417.     {
  3418.         case EOL_IGNORE:
  3419.  
  3420.             LF_Trans_Len = 0;
  3421.             break;
  3422.  
  3423.         case EOL_LF:
  3424.  
  3425.             LF_Trans_Len    = 1;
  3426.             LF_Translation    = "\n";
  3427.             break;
  3428.  
  3429.         case EOL_CR:
  3430.  
  3431.             LF_Trans_Len    = 1;
  3432.             LF_Translation    = "\r";
  3433.             break;
  3434.  
  3435.         case EOL_LFCR:
  3436.  
  3437.             LF_Trans_Len    = 2;
  3438.             LF_Translation    = "\n\r";
  3439.             break;
  3440.  
  3441.         case EOL_CRLF:
  3442.  
  3443.             LF_Trans_Len    = 2;
  3444.             LF_Translation    = "\r\n";
  3445.             break;
  3446.     }
  3447.  
  3448.     if(Config -> TerminalConfig -> ReceiveCR == EOL_CR && Config -> TerminalConfig -> ReceiveLF == EOL_LF)
  3449.         Translate_CR_LF = NULL;
  3450.     else
  3451.     {
  3452.         if(LF_Trans_Len <= 1 && CR_Trans_Len <= 1)
  3453.             Translate_CR_LF = Translate_CR_LF_1;
  3454.         else
  3455.         {
  3456.             if(LF_Trans_Len == 2 && CR_Trans_Len == 2)
  3457.                 Translate_CR_LF = Translate_CR_LF_2x2;
  3458.             else
  3459.             {
  3460.                 if(LF_Trans_Len == 2)
  3461.                     Translate_CR_LF = Translate_CR_LF_2LF;
  3462.                 else
  3463.                 {
  3464.                     if(CR_Trans_Len == 2)
  3465.                         Translate_CR_LF = Translate_CR_LF_2CR;
  3466.                     else
  3467.                         Translate_CR_LF = Translate_CR_LF_1;
  3468.                 }
  3469.             }
  3470.         }
  3471.     }
  3472.  
  3473.     Permit();
  3474. }
  3475.